<?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-1445545651031573301</id><updated>2011-12-01T17:55:09.984-08:00</updated><category term='orpc'/><category term='ocaml'/><category term='camlp4'/><category term='froc'/><category term='scala'/><category term='lwt'/><category term='ocamljs'/><category term='ocamlnet'/><category term='FRP'/><title type='text'>Ambassador to the Computers</title><subtitle type='html'>Mostly OCaml.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-7326007686288940858</id><published>2011-06-08T20:41:00.000-07:00</published><updated>2011-06-08T21:11:30.331-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Logic programming in Scala, part 3: unification and state</title><content type='html'>&lt;p&gt;In this post I want to build on the backtracking logic monad we covered &lt;a href='/2011/04/logic-programming-in-scala-part-2.html'&gt;last time&lt;/a&gt; by adding &lt;em&gt;unification&lt;/em&gt;, yielding an embedded DSL for Prolog-style logic programming.&lt;/p&gt; 
&lt;b&gt;Prolog&lt;/b&gt; 
&lt;p&gt;Here is a small Prolog example, the rough equivalent of &lt;code&gt;List.contains&lt;/code&gt; in Scala:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='prolog'&gt;  &lt;span class='nf'&gt;member&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;T&lt;/span&gt;&lt;span class='p'&gt;]).&lt;/span&gt; 
  &lt;span class='nf'&gt;member&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='p'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='p'&gt;|&lt;/span&gt;&lt;span class='nv'&gt;T&lt;/span&gt;&lt;span class='p'&gt;])&lt;/span&gt; &lt;span class='p'&gt;:-&lt;/span&gt; &lt;span class='nf'&gt;member&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;X&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;T&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;code&gt;Member&lt;/code&gt; doesn&amp;#8217;t return a boolean; instead it succeeds or fails (in the same way as the logic monad). The &lt;em&gt;goal&lt;/em&gt; &lt;code&gt;member(1, [1,2,3])&lt;/code&gt; succeeds; the goal &lt;code&gt;member(4, [1,2,3])&lt;/code&gt; fails. (What happens for &lt;code&gt;member(1, [1,1,3])&lt;/code&gt;?)&lt;/p&gt; 
 
&lt;p&gt;A Prolog &lt;em&gt;predicate&lt;/em&gt; is defined by one or more &lt;em&gt;clauses&lt;/em&gt; (each ending in a period), made up of a &lt;em&gt;head&lt;/em&gt; (the predicate and arguments before the &lt;code&gt;:-&lt;/code&gt;) and zero or more &lt;em&gt;subgoals&lt;/em&gt; (goals after the &lt;code&gt;:-&lt;/code&gt;, separated by commas; if there are no subgoals the &lt;code&gt;:-&lt;/code&gt; is omitted). To solve a goal, we &lt;em&gt;unify&lt;/em&gt; it (match it) with each clause head, then solve each subgoal in the clause. If a subgoal fails we backtrack and try the next matching head; if there is no matching head the goal fails. A goal may succeed more than once.&lt;/p&gt; 
 
&lt;p&gt;For &lt;code&gt;member&lt;/code&gt; we have two clauses: the first says that &lt;code&gt;member&lt;/code&gt; succeeds if &lt;code&gt;X&lt;/code&gt; is the head of the list (&lt;code&gt;[X|T]&lt;/code&gt; is the same as &lt;code&gt;x::t&lt;/code&gt; in Scala); the second says that &lt;code&gt;member&lt;/code&gt; succeeds if &lt;code&gt;X&lt;/code&gt; is a member of the tail of the list, regardless of the head. There is no clause where the list is empty (written &lt;code&gt;[]&lt;/code&gt;); a goal with an empty list fails since there is no matching clause head.&lt;/p&gt; 
 
&lt;p&gt;Prolog unification is more expressive than pattern matching as found in Scala, OCaml, etc. Both sides of a unification may contain variables; unification attempts to instantiate them so that the two sides are equal. Variables are instantiated by &lt;em&gt;terms&lt;/em&gt;, which themselves may contain variables; unification finds the most general instantiation which makes the sides equal.&lt;/p&gt; 
 
&lt;p&gt;As a small example of this expressivity, we can run &lt;code&gt;member&lt;/code&gt; &amp;#8220;backwards&amp;#8221;: the goal &lt;code&gt;member(X, [1,2,3])&lt;/code&gt; succeeds once for each element of the list, with &lt;code&gt;X&lt;/code&gt; bound to the element.&lt;/p&gt; 
 
&lt;p&gt;There is much more on Prolog and logic programming in &lt;a href='http://www.cs.cmu.edu/~fp/courses/lp/lectures/lp-all.pdf'&gt;Frank Pfenning&amp;#8217;s course notes&lt;/a&gt;, which I recommend highly.&lt;/p&gt; 
&lt;b&gt;Unification&lt;/b&gt; 
&lt;p&gt;For each type we want to use in unification we&amp;#8217;ll define a corresponding type of terms, which have the same structure as the underlying type but can also contain variables. These aren&amp;#8217;t Scala variables (which of course can&amp;#8217;t be stored in a data structure) but &amp;#8220;existential variables&amp;#8221;, or &lt;em&gt;evars&lt;/em&gt;. Evars are just tags; computations will carry an &lt;em&gt;environment&lt;/em&gt; mapping evars to terms, which may be updated after a successful unification.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;scala.collection.immutable.&lt;/span&gt;&lt;span class='o'&gt;{&lt;/span&gt;&lt;span class='nc'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='nc'&gt;HashMap&lt;/span&gt;&lt;span class='o'&gt;}&lt;/span&gt; 
 
&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;String&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='c1'&gt;// invariant: on call to unify, this and t have e substituted&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Boolean&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ground&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The important property of an evar is that it is distinct from every other evar; the name attached to it is just a label. An evar is indexed by a phantom type indicating the underlying type of terms which may be bound to it.&lt;/p&gt; 
 
&lt;p&gt;A term is indexed by its underlying type. So &lt;code&gt;Int&lt;/code&gt; becomes &lt;code&gt;Term[Int]&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt; becomes &lt;code&gt;Term[String]&lt;/code&gt;, and so on; an evar of type &lt;code&gt;Evar[A]&lt;/code&gt; may only be bound to a term of type &lt;code&gt;Term[A]&lt;/code&gt;. (Prolog is dynamically typed, but this statically-typed treatment of evars and terms fits better with Scala.)&lt;/p&gt; 
 
&lt;p&gt;The &lt;code&gt;unify&lt;/code&gt; method unifies a term with another term of the same type, taking an environment and returning an updated environment (or &lt;code&gt;None&lt;/code&gt; if the unification fails). &lt;code&gt;Occurs&lt;/code&gt; checks if an evar occurs in a term (as we will see this is used to prevent circular bindings). &lt;code&gt;Subst&lt;/code&gt; substitutes the variables in a term with their bindings in an environment, and &lt;code&gt;ground&lt;/code&gt; returns the underlying Scala value represented by the term (provided the term contains no evars).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;,&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]]).&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]]).&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;updated&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;v2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v2&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;mapValues&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;_&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;updated&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Env&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;,&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;empty&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;HashMap&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;An environment is just a map from evars to terms. Because we need to store evars and terms of different types in the same environment, we cast them to and from &lt;code&gt;Any&lt;/code&gt;; this is safe because of the phantom type on &lt;code&gt;Evar&lt;/code&gt;. For simplicity we maintain the invariant that the term bound to each evar is already substituted by the rest of the environment.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v2&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
        &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;updated&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;v2&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ground&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;throw&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;IllegalArgumentException&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;not ground&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;name&lt;/span&gt;  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;VarTerm&lt;/code&gt; class represents terms consisting of an evar. To unify a &lt;code&gt;VarTerm&lt;/code&gt; with another &lt;code&gt;VarTerm&lt;/code&gt; containing the same evar, we just return the environment unchanged (since there is no new information). Otherwise we check that the evar doesn&amp;#8217;t appear in the term (since a unification &lt;code&gt;x =:= List(x)&lt;/code&gt; would create a circular term) then return the updated environment.&lt;/p&gt; 
 
&lt;p&gt;To substitute a &lt;code&gt;VarTerm&lt;/code&gt; we return the term bound to the evar in the environment if one exists, otherwise the unsubstituted &lt;code&gt;VarTerm&lt;/code&gt;. A &lt;code&gt;VarTerm&lt;/code&gt; is never ground (we assume &lt;code&gt;ground&lt;/code&gt; is called only on terms which are already substituted by the environment).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;LitTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;LitTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;a2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;_:&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ground&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; 
 
  &lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;code&gt;LitTerm&lt;/code&gt; represents terms of literal Scala values. A &lt;code&gt;LitTerm&lt;/code&gt; unifies with another &lt;code&gt;LitTerm&lt;/code&gt; containing an equal value, but that adds nothing to the environment. Then we have two cases which we need for every term type&amp;#8212;to unify with a &lt;code&gt;VarTerm&lt;/code&gt; call &lt;code&gt;unify&lt;/code&gt; back on it; otherwise fail.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;NilTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]()&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;NilTerm&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;_:&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ground&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
 
  &lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
 
&lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; 
  &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
&lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hd2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tl2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
          &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;hd2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='n'&gt;e2&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e1&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tl2&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e1&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
        &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;_:&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='k'&gt;this&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;C&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;C&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;occurs&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;ground&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ground&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;ground&lt;/span&gt; 
 
  &lt;span class='k'&gt;override&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='s'&gt;&amp;quot; :: &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;toString&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;code&gt;NilTerm&lt;/code&gt; and &lt;code&gt;ConsTerm&lt;/code&gt; represent the &lt;code&gt;Nil&lt;/code&gt; and &lt;code&gt;::&lt;/code&gt; constructors for lists. &lt;code&gt;Nil&lt;/code&gt; is sort of like a literal, so the methods for &lt;code&gt;NilTerm&lt;/code&gt; are similar to those for &lt;code&gt;LitTerm&lt;/code&gt;. For &lt;code&gt;ConsTerm&lt;/code&gt; we unify by unifying the heads and tails, calling &lt;code&gt;subst&lt;/code&gt; on the tails since unifying the heads may have added bindings to the environment. (Here it&amp;#8217;s convenient to use a for-comprehension on the &lt;code&gt;Option[Env]&lt;/code&gt; type since either unification may fail.) Similarly we implement &lt;code&gt;occurs&lt;/code&gt;, &lt;code&gt;subst&lt;/code&gt;, and &lt;code&gt;ground&lt;/code&gt; by calling them on the head and tail.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;var2Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;VarTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;v&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='c1'&gt;//implicit def lit2term[A](a: A): Term[A] = LitTerm(a)&lt;/span&gt; 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;int2Term&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;LitTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;list2Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;NilTerm&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;list2Term&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Finally we have some implicit conversions to make it a little easier to build &lt;code&gt;Term&lt;/code&gt; values. The &lt;code&gt;lit2term&lt;/code&gt; conversion turned out to be a bad idea; in particular you don&amp;#8217;t want a &lt;code&gt;LitTerm[List[A]]&lt;/code&gt; since it doesn&amp;#8217;t unify with a &lt;code&gt;ConsTerm[A]&lt;/code&gt; or &lt;code&gt;NilTerm[A]&lt;/code&gt;.&lt;/p&gt; 
&lt;b&gt;State&lt;/b&gt; 
&lt;p&gt;In order to combine unification with backtracking, we need to keep track of the environment along each branch of the tree of choices. We don&amp;#8217;t want the environments from different branches to interfere, so it&amp;#8217;s convenient to use a purely functional environment representation; we pass the current environment down the tree as computation proceeds. However, we can hide this state passing in the monad interface:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='c1'&gt;// as before&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;, &lt;span class='kt'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Syntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='c1'&gt;// as before&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;_:&lt;/span&gt; &lt;span class='n'&gt;A&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;code&gt;LogicState&lt;/code&gt; is mostly the same as &lt;code&gt;Logic&lt;/code&gt;, except that the type of choices has an extra parameter for the type of the state. The &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; functions get and set the current state. To &lt;code&gt;split&lt;/code&gt; we need an initial state to get things started, and each result includes an updated state. Finally we add the syntax &lt;code&gt;&amp;amp;&lt;/code&gt; to sequence two computations, ignoring the value of the first. We&amp;#8217;ll use this to sequence goals, since we care only about the updated environment.&lt;/p&gt; 
 
&lt;p&gt;The simplest implementation of &lt;code&gt;LogicState&lt;/code&gt; builds on &lt;code&gt;Logic&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;LogicStateT&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Logic&lt;/span&gt; 
 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;, &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We embed state-passing in a &lt;code&gt;Logic.T&lt;/code&gt; as a function from an initial state to a choice of alternatives, where each alternative includes an updated state along with its value.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;fail&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;f2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;f2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;f2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;f2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;_&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;All of these operations pass the state through unchanged. Note that &lt;code&gt;or&lt;/code&gt; passes the same state to both alternatives&amp;#8212;different branches of the tree cannot interfere with one another&amp;#8217;s state.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(((&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;}))&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;_:&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;,()))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;In &lt;code&gt;split&lt;/code&gt; we pass the given state to the underlying &lt;code&gt;Logic.T&lt;/code&gt;, and for each alternative we unpack the pair of state and value. The choice of remaining alternatives &lt;code&gt;t&lt;/code&gt; encapsulates the current state, so when we return it we ignore the input state. In &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; we return and replace the current state.&lt;/p&gt; 
 
&lt;p&gt;Another approach is to pass state explicitly through &lt;code&gt;LogicSFK&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;LogicStateSFK&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;R&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;A&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;R&lt;/span&gt; 
 
  &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;S&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;S&lt;/span&gt;,&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This is not really any different from &lt;code&gt;LogicStateT&lt;/code&gt; applied to &lt;code&gt;LogicSFK&lt;/code&gt;&amp;#8212;we have just uncurried the state argument. We can take the same path as last time and defunctionalize this into a tail-recursive implementation (see the &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/scala-logic'&gt;full code&lt;/a&gt;) although &lt;code&gt;LogicStateT&lt;/code&gt; applied to &lt;code&gt;LogicSFKDefuncTailrec&lt;/code&gt; inherits tail-recursiveness from the underlying &lt;code&gt;Logic&lt;/code&gt; monad.&lt;/p&gt; 
&lt;b&gt;Scrolog&lt;/b&gt; 
&lt;p&gt;Finally we can put the pieces together into a Prolog-like embedded DSL:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Scrolog&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;LogicState&lt;/span&gt; 
  &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;LogicState._&lt;/span&gt; 
 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Env&lt;/span&gt;,&lt;span class='kt'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;From our point of view, a goal is a stateful choice among alternatives, where we don&amp;#8217;t care about the value returned, only the environment.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;TermSyntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='o'&gt;=:=(&lt;/span&gt;&lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='n'&gt;env&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;get&lt;/span&gt; 
        &lt;span class='n'&gt;env2&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
          &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;unify&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;env&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
            &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Env&lt;/span&gt;,&lt;span class='kt'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
            &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;set&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='o'&gt;}&lt;/span&gt; 
        &lt;span class='o'&gt;}&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='n'&gt;env2&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;termSyntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;TermSyntax&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;syntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;syntax&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We connect term unification to the stateful logic monad with a wrapper class defining a &lt;code&gt;=:=&lt;/code&gt; operator. To unify terms in the monad, we get the current environment, substitute it into the two terms (to satisfy the invariant above), then call &lt;code&gt;unify&lt;/code&gt;; if it fails we fail the computation, else we set the new state.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tm&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='nc'&gt;LogicState&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Env&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;empty&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;({&lt;/span&gt; &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;_&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;tm&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;subst&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;run&lt;/code&gt; function solves a goal, taking as arguments the goal, the maximum number of solutions to find, and a term to be evaluated in the environment of each solution.&lt;/p&gt; 
&lt;b&gt;Examples&lt;/b&gt; 
&lt;p&gt;First we need to set up Scrolog:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Scrolog&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;Scrolog&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;LogicState&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;LogicStateT&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;LogicSFKDefuncTailrec&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;Scrolog._&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Here is a translation of the &lt;code&gt;member&lt;/code&gt; predicate:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;member&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;hd&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;hd&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;tl&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;ConsTerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;member&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;tl&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We implement predicates by functions, and goals by function calls. To implement matching the clause head, we explicitly unify the input arguments against each clause head, and combine the clauses with &lt;code&gt;|&lt;/code&gt;. Subgoals are sequenced with &lt;code&gt;&amp;amp;&lt;/code&gt;. Finally, we must create local evars explicitly, since they are fresh for each call (just as local variables are in Scala).&lt;/p&gt; 
 
&lt;p&gt;Finally we can run the goal above:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;member&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='o'&gt;)),&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;res6&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;As another example, we can implement addition over unary natural numbers. In Prolog this would be&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='prolog'&gt;  &lt;span class='nf'&gt;sum&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s-Atom'&gt;z&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt; 
  &lt;span class='nf'&gt;sum&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nf'&gt;s&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;M&lt;/span&gt;&lt;span class='p'&gt;),&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nf'&gt;s&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;P&lt;/span&gt;&lt;span class='p'&gt;))&lt;/span&gt; &lt;span class='p'&gt;:-&lt;/span&gt; &lt;span class='nf'&gt;sum&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='nv'&gt;M&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;N&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nv'&gt;P&lt;/span&gt;&lt;span class='p'&gt;).&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;In Prolog we can just invent symbols like &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt;; in Scala we need first to define a type of natural numbers, then terms over that type:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Nat&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Z&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Nat&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Nat&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;ZTerm&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='c1'&gt;// like NilTerm&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;STerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='c1'&gt;// like ConsTerm&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Then we can define &lt;code&gt;sum&lt;/code&gt;, again separating the clauses by &lt;code&gt;|&lt;/code&gt; and explicitly unifying the clause heads:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;G&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;m2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;m&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;p&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='n'&gt;Z&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='nc'&gt;STerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=:=&lt;/span&gt; &lt;span class='nc'&gt;STerm&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt; &lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;m2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We can use &lt;code&gt;sum&lt;/code&gt; to do addition:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;x&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Evar&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='s'&gt;&amp;quot;y&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)),&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;res8&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;))))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;or subtraction:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)),&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))),&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;res10&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))),&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;res11&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;or even to find all the pairs of naturals which sum to 3:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sum&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))),&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
&lt;span class='n'&gt;res14&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Term&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Nat&lt;/span&gt;&lt;span class='o'&gt;]]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
  &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(),&lt;/span&gt; 
       &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(),&lt;/span&gt; 
       &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(),&lt;/span&gt; 
       &lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;S&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;Z&lt;/span&gt;&lt;span class='o'&gt;)))&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;Z&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;although the printing of &lt;code&gt;Term[List]&lt;/code&gt; could be better.&lt;/p&gt; 
 
&lt;p&gt;This is only a small taste of the expressivity of Prolog-style logic programming. Again let me recommend &lt;a href='http://www.cs.cmu.edu/~fp/courses/lp/lectures/lp-all.pdf'&gt;Frank Pfenning&amp;#8217;s course notes&lt;/a&gt;, which explore the semantics of Prolog in a &amp;#8220;definitional interpreters&amp;#8221; style, by gradually refining an interpreter to expose more of the machinery of the language.&lt;/p&gt; 
 
&lt;p&gt;See the &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/scala-logic'&gt;full code&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-7326007686288940858?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/7326007686288940858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/06/logic-programming-in-scala-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/7326007686288940858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/7326007686288940858'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/06/logic-programming-in-scala-part-3.html' title='Logic programming in Scala, part 3: unification and state'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-1309587949974670725</id><published>2011-04-29T22:07:00.000-07:00</published><updated>2011-06-08T20:39:18.549-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Logic programming in Scala, part 2: backtracking</title><content type='html'>&lt;p&gt;In the &lt;a href='/2011/04/logic-programming-in-scala-part-1.html'&gt;previous post&lt;/a&gt; we saw how to write computations in a logic monad, where a &amp;#8220;value&amp;#8221; is a choice among alternatives, and operating on a value means operating on all the alternatives.&lt;/p&gt; 
 
&lt;p&gt;Our first implementation of the logic monad represents a choice among alternatives as a list, and operating on a value means running the operation for each alternative immediately (to produce a new list of alternatives). If we imagine alternatives as leaves of a tree (with &lt;code&gt;|&lt;/code&gt; indicating branching), the first implementation explores the tree breadth-first.&lt;/p&gt; 
 
&lt;p&gt;This is OK for some problems, but we run into trouble when there are a large or infinite number of alternatives. For example, a choice among the natural numbers:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;LogicList._&lt;/span&gt; 
&lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;LogicList._&lt;/span&gt; 
 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lang&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;NullPointerException&lt;/span&gt; 
        &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This goes wrong because even though the right-hand argument to &lt;code&gt;|&lt;/code&gt; is by-name, we immediately try to use it, and fail because &lt;code&gt;nat&lt;/code&gt; is not yet defined.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;LogicList.T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lang&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;StackOverflowError&lt;/span&gt; 
        &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;With &lt;code&gt;def&lt;/code&gt; we can successfully define &lt;code&gt;nat&lt;/code&gt;, because the right-hand side isn&amp;#8217;t evaluated until &lt;code&gt;nat&lt;/code&gt; is used in the call to &lt;code&gt;run&lt;/code&gt;, but we overflow the stack trying to compute all the natural numbers.&lt;/p&gt; 
 
&lt;p&gt;Let&amp;#8217;s repair this with a fancier implementation of the logic monad, translated from Kiselyov et al.&amp;#8217;s &lt;a href='http://okmij.org/ftp/Computation/LogicT.pdf'&gt;Backtracking, Interleaving, and Terminating Monad Transformers&lt;/a&gt;. This implementation will explore the tree depth-first.&lt;/p&gt; 
&lt;b&gt;Success and failure continuations&lt;/b&gt; 
&lt;p&gt;The idea is to represent a choice of alternatives by a function, which takes as arguments two functions: a &lt;em&gt;success continuation&lt;/em&gt; and a &lt;em&gt;failure continuation&lt;/em&gt;. The success continuation is just a function indicating what to do next with each alternative; the failure continuation is what to do next when there are no more alternatives.&lt;/p&gt; 
 
&lt;p&gt;For success, what we do next is either return the alternative (when we have reached a leaf of the tree), or perform some operation on it (possibly forming new branches rooted at the alternative). For failure, what we do next is back up to the last branch point and succeed with the next alternative. If there are no more alternatives at the previous branch point we back up again, and so on until we can succeed or finally run out of alternatives. In other words, we do depth-first search on the tree, except that the tree isn&amp;#8217;t a materialized data structure&amp;#8212;it&amp;#8217;s created on the fly.&lt;/p&gt; 
 
&lt;p&gt;(In the jargon of logic programming, a branch point is called a &amp;#8220;choice point&amp;#8221;, and going back to an earlier choice point is called &amp;#8220;backtracking&amp;#8221;.)&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;LogicSFK&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;R&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;A&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;R&lt;/span&gt; 
 
  &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The continuations can return a result of some arbitrary type &lt;code&gt;R&lt;/code&gt;. This means that the function representing a choice has a &amp;#8220;rank-2&amp;#8221; polymorphic type&amp;#8212;it takes functions which are themselves polymorphic&amp;#8212;which is not directly representable in Scala. But we can encode it by making the representation function a method on a trait.&lt;/p&gt; 
 
&lt;p&gt;The success continuation takes a value of the underlying type (i.e. an alternative), and also a failure continuation, to call in case this branch of the tree eventually fails (by calling &lt;code&gt;fail&lt;/code&gt;, or &lt;code&gt;filter&lt;/code&gt; when no alternative satisfies the predicate). The failure continuation is also called to succeed with the next alternative after returning a leaf (see &lt;code&gt;split&lt;/code&gt;).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;To fail, just call the failure continuation. To succeed with one alternative, call the success continuation with the single alternative and the passed-in failure continuation&amp;#8212;there are no more alternatives to try, so if this branch fails the &lt;code&gt;unit&lt;/code&gt; fails.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
        &lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;code&gt;Or&lt;/code&gt; creates a choice point. We want to explore the alternatives in both &lt;code&gt;t1&lt;/code&gt; and &lt;code&gt;t2&lt;/code&gt;, so we pass the success continuation to &lt;code&gt;t1&lt;/code&gt; (which calls it on each alternative); when &lt;code&gt;t1&lt;/code&gt; is exhausted we pass the success continuation to &lt;code&gt;t2&lt;/code&gt;; finally we fail with the caller&amp;#8217;s failure continuation&amp;#8212;that is, we backtrack.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
        &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(({&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
        &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(({&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;For &lt;code&gt;bind&lt;/code&gt; we extend each branch by calling &lt;code&gt;f&lt;/code&gt; on the current leaf. To succeed we call &lt;code&gt;f&lt;/code&gt; on the alternative &lt;code&gt;a&lt;/code&gt;. Now &lt;code&gt;f(a)&lt;/code&gt; returns a choice of alternatives, so we pass it the original success continuation (which says what to do next with alternatives resulting from the &lt;code&gt;bind&lt;/code&gt;), and the failure continuation in force at the point &lt;code&gt;a&lt;/code&gt; was generated (which succeeds with the next available alternative from &lt;code&gt;f(a)&lt;/code&gt;).&lt;/p&gt; 
 
&lt;p&gt;For &lt;code&gt;apply&lt;/code&gt; things are simpler, since &lt;code&gt;f(a)&lt;/code&gt; returns a single value rather than a choice of alternatives: we succeed immediately with the returned value.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;sk2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
          &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
        &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;To filter a choice of alternatives, each time we succeed with a value we see if it satisfies the predicate &lt;code&gt;p&lt;/code&gt;; if it does, we succeed with that value (extending the branch), otherwise we fail (pruning the branch).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt; &lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
      &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;unsplit&lt;/span&gt;&lt;span class='o'&gt;)))&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The point of &lt;code&gt;split&lt;/code&gt; is to pull a single alternative from a choice, returning along with it a choice of the remaining alternatives. In the list implementation we just returned the head and tail of the list. In this implementation, the alternatives are computed on demand; we want to be careful to do only as much computation as needed to pull the first alternative&lt;/p&gt; 
 
&lt;p&gt;The failure continuation we pass to &lt;code&gt;t&lt;/code&gt; just returns &lt;code&gt;None&lt;/code&gt; when there are no more alternatives. The success continuation &lt;code&gt;sk&lt;/code&gt; returns the first alternative and a choice of the remaining alternatives (wrapped in &lt;code&gt;Some&lt;/code&gt;).&lt;/p&gt; 
 
&lt;p&gt;The tricky part is the choice of remaining alternatives. We&amp;#8217;re given the failure continuation &lt;code&gt;fk&lt;/code&gt;; calling it calls &lt;code&gt;sk&lt;/code&gt; on the next alternative, which ultimately returns &lt;code&gt;Some(a, t)&lt;/code&gt; where &lt;code&gt;a&lt;/code&gt; is the next alternative, or &lt;code&gt;None&lt;/code&gt; if there are no more alternatives. We repackage this &lt;code&gt;Option&lt;/code&gt; as a choice of alternatives with &lt;code&gt;unsplit&lt;/code&gt;. So that we don&amp;#8217;t call &lt;code&gt;fk&lt;/code&gt; too soon, we call &lt;code&gt;unsplit&lt;/code&gt; via &lt;code&gt;bind&lt;/code&gt;, which defers the call until the resulting choice of alternatives is actually used.&lt;/p&gt; 
 
&lt;p&gt;Now we can write infinite choices:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;LogicSFK._&lt;/span&gt; 
&lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;LogicSFK._&lt;/span&gt; 
 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;LogicSFK.T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;LogicSFK$$anon$3&lt;/span&gt;&lt;span class='o'&gt;@&lt;/span&gt;&lt;span class='mi'&gt;27&lt;/span&gt;&lt;span class='n'&gt;aea0c1&lt;/span&gt; 
 
&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;res1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;3&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;4&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;6&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;7&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;8&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Well, this is a pretty complicated way to generate the natural numbers up to 10&amp;#8230;&lt;/p&gt; 
 
&lt;p&gt;While &lt;code&gt;nat&lt;/code&gt; looks like a lazy stream (as you might write in Haskell), no results are memoized (as they are in Haskell). To compute each successive number all the previous ones must be recomputed, and the running time of &lt;code&gt;run(nat, N)&lt;/code&gt; is O(N&lt;sup&gt;2&lt;/sup&gt;).&lt;/p&gt; 
&lt;b&gt;Defunctionalization&lt;/b&gt; 
&lt;p&gt;The code above is a fairly direct translation of the Haskell code from the paper. But its use of continuation-passing style doesn&amp;#8217;t map well to Scala, because Scala doesn&amp;#8217;t implement tail-call elimination (because the JVM doesn&amp;#8217;t). Every call to a success or failure continuation adds a frame to the stack, even though all we ever do with the result is return it (i.e. the call is in &lt;em&gt;tail-position&lt;/em&gt;), so the stack frame could be eliminated.&lt;/p&gt; 
 
&lt;p&gt;Surprisingly, we run out of memory before we run out of stack:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2000&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lang&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;OutOfMemoryError&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Java&lt;/span&gt; &lt;span class='kt'&gt;heap&lt;/span&gt; &lt;span class='kt'&gt;space&lt;/span&gt; 
 &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A little heap profiling shows that we&amp;#8217;re using quadratic space as well as quadratic time. It turns out that the implementation of &lt;code&gt;Logic.run&lt;/code&gt; (from the previous post) has a space leak. The call to &lt;code&gt;run&lt;/code&gt; is not tail-recursive, so the stack frame hangs around, and although &lt;code&gt;t&lt;/code&gt; is dead after &lt;code&gt;split(t)&lt;/code&gt;, there&amp;#8217;s still a reference to it on the stack.&lt;/p&gt; 
 
&lt;p&gt;We can rewrite &lt;code&gt;run&lt;/code&gt; with an accumulator to be tail-recursive:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;runAcc&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;acc&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;acc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reverse&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; 
        &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
          &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;acc&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;reverse&lt;/span&gt; 
          &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;runAcc&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;acc&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='n'&gt;runAcc&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Now &lt;code&gt;scalac&lt;/code&gt; compiles &lt;code&gt;runAcc&lt;/code&gt; as a loop, so there are no stack frames holding on to dead values of &lt;code&gt;t&lt;/code&gt;, and we get the expected:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;9000&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='n'&gt;java&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lang&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;StackOverflowError&lt;/span&gt; 
 &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;To address the stack overflow we turn to &lt;em&gt;defunctionalization&lt;/em&gt;. The idea (from John Reynold&amp;#8217;s classic paper &lt;a href='http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.110.5892&amp;amp;rep=rep1&amp;amp;type=pdf'&gt;Definitional Interpreters for Higher-Order Programming Languages&lt;/a&gt;) is to replace functions and their applications with data constructors (we&amp;#8217;ll use case classes) and an &lt;code&gt;apply&lt;/code&gt; function, which matches the data constructor and does whatever the corresponding function body does. If a function captures variables, the data constructor must capture the same variables.&lt;/p&gt; 
 
&lt;p&gt;After defunctionalization we&amp;#8217;re left with three mutually recursive &lt;code&gt;apply&lt;/code&gt; functions (one for each of &lt;code&gt;T&lt;/code&gt;, &lt;code&gt;FK&lt;/code&gt;, and &lt;code&gt;SK&lt;/code&gt;) where each recursive call is in tail position. In theory the compiler could transform these into code that takes only constant stack space (since they are local functions private to &lt;code&gt;split&lt;/code&gt;). But in fact it will do so only for single recursive functions, so we will need to do this transformation by hand.&lt;/p&gt; 
 
&lt;p&gt;There is one hitch: the original code is not completely tail-recursive, because of &lt;code&gt;unsplit&lt;/code&gt;, which calls a failure continuation then matches on the result. To fix this we need to add yet another continuation, which represents what to do after returning a result from a success or failure continuation.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;LogicSFKDefunc&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]&lt;/span&gt; 
 
  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='nc'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]()&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A choice of alternatives &lt;code&gt;T[A]&lt;/code&gt; is now represented symbolically by case classes, and the functions which operate on choices just return the corresponding case. The cases capture the same variables that were captured in the original functions.&lt;/p&gt; 
 
&lt;p&gt;We have an additional case &lt;code&gt;Unsplit&lt;/code&gt; which represents the &lt;code&gt;bind(unit(fk), unsplit)&lt;/code&gt; combination from &lt;code&gt;split&lt;/code&gt;. And we use &lt;code&gt;O[A]&lt;/code&gt; as a convenient abbreviation.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='nc'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
    &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='nc'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
    &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
    &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
    &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;R&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='nc'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;KReturn&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]()&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt;&lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
    &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Each case for &lt;code&gt;FK&lt;/code&gt; (respectively &lt;code&gt;SK&lt;/code&gt;) corresponds to a success (respectively failure) continuation function in the original code&amp;#8212;it&amp;#8217;s easy to match them up.&lt;/p&gt; 
 
&lt;p&gt;The &lt;code&gt;K&lt;/code&gt; cases are for the new return continuation. They are defunctionalized from functions &lt;code&gt;R =&amp;gt; R2&lt;/code&gt;; we can either return a value directly, or match on whether it is &lt;code&gt;Some&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt; as in &lt;code&gt;unsplit&lt;/code&gt;. (If &lt;code&gt;K&lt;/code&gt; is hard to understand you might try &amp;#8220;refunctionalizing&amp;#8221; it by replacing the cases with functions.)&lt;/p&gt; 
 
&lt;p&gt;We see that case classes are more powerful than variants in OCaml, without &lt;a href='https://sites.google.com/site/ocamlgadt/'&gt;GADTs&lt;/a&gt; at least. Cases can have &amp;#8220;input&amp;#8221; type variables (appearing in arguments) which do not appear in the &amp;#8220;output&amp;#8221; (the type the case extends). When we match on the case these are treated as existentials. And the output type of a case can be more restrictive than type it extends; when we match on the case we can make more restrictive assumptions about types in that branch of the match. More on this in Emir, Odersky, and Williams&amp;#8217; &lt;a href='http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5295&amp;amp;rep=rep1&amp;amp;type=pdf'&gt;Matching Objects with Patterns&lt;/a&gt;.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyFK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applySK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyFK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;applyFK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;fk&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(),&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;applySK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;SK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;FK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;sk&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applySK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='n'&gt;applySK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;applyFK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rf&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;rf&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Again, each of these cases corresponds directly to a function in the original code, and again it is easy to match them up (modulo the extra return continuation argument) to see that all we have done is separated the data part of the function (i.e. the captured variables) from the code part.&lt;/p&gt; 
 
&lt;p&gt;The exception is &lt;code&gt;Unsplit&lt;/code&gt;, which again corresponds to &lt;code&gt;bind(unit(fk),
unsplit)&lt;/code&gt;. To apply it, we apply &lt;code&gt;fk&lt;/code&gt; (which collapses &lt;code&gt;unit(fk)&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, and the application of &lt;code&gt;fk&lt;/code&gt; in &lt;code&gt;unsplit&lt;/code&gt;) with &lt;code&gt;KUnsplit&lt;/code&gt; as continuation, capturing &lt;code&gt;sk&lt;/code&gt;, &lt;code&gt;fk&lt;/code&gt;, and &lt;code&gt;k&lt;/code&gt; (corresponding to their capture in the success continuation of &lt;code&gt;bind&lt;/code&gt;).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;applyK&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;K&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R&lt;/span&gt;,&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;R2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;KReturn&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;R2&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
          &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
            &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyFK&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
            &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='o'&gt;}&lt;/span&gt; 
        &lt;span class='o'&gt;}&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;For &lt;code&gt;KReturn&lt;/code&gt; we just return the result. Although &lt;code&gt;KReturn&lt;/code&gt; extends &lt;code&gt;K[R,R]&lt;/code&gt;, Scala doesn&amp;#8217;t deduce from this that &lt;code&gt;R&lt;/code&gt; = &lt;code&gt;R2&lt;/code&gt;, so we must coerce the result. For &lt;code&gt;KUnsplit&lt;/code&gt; we do the same match as &lt;code&gt;unsplit&lt;/code&gt;, then apply the resulting &lt;code&gt;T&lt;/code&gt; (for the &lt;code&gt;None&lt;/code&gt; case we call the failure continuation directly instead of applying &lt;code&gt;fail&lt;/code&gt;). Here Scala deduces from the return type of &lt;code&gt;KUnsplit&lt;/code&gt; that is safe to treat &lt;code&gt;r&lt;/code&gt; as an &lt;code&gt;Option&lt;/code&gt;.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;    &lt;span class='n'&gt;applyT&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;,&lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt; 
      &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
      &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)))),&lt;/span&gt; 
      &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; 
      &lt;span class='nc'&gt;KReturn&lt;/span&gt;&lt;span class='o'&gt;())&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Finally we apply the input &lt;code&gt;T&lt;/code&gt; in correspondence to the original &lt;code&gt;split&lt;/code&gt;.&lt;/p&gt; 
&lt;b&gt;Tail call elimination&lt;/b&gt; 
&lt;p&gt;(This section has been revised; you can see the original &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/ba9621fc48ff84e01d9f70d076cc912b8185729d'&gt;here&lt;/a&gt;.)&lt;/p&gt; 
 
&lt;p&gt;To eliminate the stack frames from tail calls, we next rewrite the four mutually-recursive functions into a single recursive function (which Scala compiles as a loop). To do this we have to abandon some type safety (but only in the implementation of the &lt;code&gt;Logic&lt;/code&gt; monad; we&amp;#8217;ll still present the same safe interface).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;LogicSFKDefuncTailrec&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]&lt;/span&gt; 
 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
 
  &lt;span class='k'&gt;sealed&lt;/span&gt; &lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;KReturn&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='n'&gt;I&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This is all pretty much as before except that we erase all the type parameters. Having done so we can combine the four defunctionalized types into a single type &lt;code&gt;I&lt;/code&gt; (for &amp;#8220;instruction&amp;#8221; perhaps), which will allow us to write a single recursive &lt;code&gt;apply&lt;/code&gt; function. The type parameter in &lt;code&gt;T[A]&lt;/code&gt; is then a &lt;em&gt;phantom type&lt;/em&gt; since it does not appear on the right-hand side of the definition; it is used only to enforce constraints outside the module.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt; &lt;span class='o'&gt;})&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The functions for building &lt;code&gt;T[A]&lt;/code&gt; values are mostly the same. We have to cast passed-in functions since &lt;code&gt;Any&lt;/code&gt; is not a subtype of arbitrary &lt;code&gt;A&lt;/code&gt;. The return type annotations don&amp;#8217;t seem necessary but I saw some strange type errors without them (possibly related to the phantom type?) when using the &lt;code&gt;Logic.Syntax&lt;/code&gt; wrapper.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;I&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Any&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Fail&lt;/span&gt;&lt;span class='o'&gt;()&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;FKOr&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;(),&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKBind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKApply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
          &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;else&lt;/span&gt; 
          &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;rf&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;rf&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;KReturn&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;KUnsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
          &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;sk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='o'&gt;}&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
        &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
        &lt;span class='kc'&gt;null&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
        &lt;span class='nc'&gt;SKSplit&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Unsplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fk&lt;/span&gt;&lt;span class='o'&gt;)))),&lt;/span&gt; 
        &lt;span class='nc'&gt;FKSplit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; 
        &lt;span class='nc'&gt;KReturn&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;asInstanceOf&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;O&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The original functions took varying arguments; the single function takes all the arguments which the original ones did. We pass &lt;code&gt;null&lt;/code&gt; for unused arguments in each call, but otherwise the cases are the same as before.&lt;/p&gt; 
 
&lt;p&gt;Now we can evaluate &lt;code&gt;nat&lt;/code&gt; to large N without running out of stack (but since the running time is quadratic it takes longer than I care to wait to complete):&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;nat&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;100000&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='o'&gt;^&lt;/span&gt;&lt;span class='n'&gt;C&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;See the complete code &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/scala-logic'&gt;here&lt;/a&gt;.&lt;/p&gt; 
 
&lt;p&gt;Next time we&amp;#8217;ll thread state through this backtracking logic monad, and use it to implement unification.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-1309587949974670725?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/1309587949974670725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-2.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/1309587949974670725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/1309587949974670725'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-2.html' title='Logic programming in Scala, part 2: backtracking'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-3020455680296288063</id><published>2011-04-06T22:03:00.000-07:00</published><updated>2011-05-02T21:02:15.805-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Logic programming in Scala, part 1</title><content type='html'>&lt;p&gt;I got a new job where I am hacking some Scala. I thought I would learn something by translating some functional code into Scala, and a friend had recently pointed me to Kiselyov et al.&amp;#8217;s &lt;a href='http://okmij.org/ftp/Computation/LogicT.pdf'&gt;Backtracking, Interleaving, and Terminating Monad Transformers&lt;/a&gt;, which provides a foundation for Prolog-style logic programming. Of course, a good translation should use the local idiom. So in this post (and the next) I want to explore an embedded domain-specific language for logic programming in Scala.&lt;/p&gt; 
&lt;b&gt;A search problem&lt;/b&gt; 
&lt;p&gt;Here is a problem I sometimes give in interviews:&lt;/p&gt; 
 
&lt;blockquote&gt; 
&lt;p&gt;Four people need to cross a rickety bridge, which can hold only two people at a time. It&amp;#8217;s a moonless night, so they need a light to cross; they have one flashlight with a battery which lasts 60 minutes. Each person crosses the bridge at a different speed: Alice takes 5 minutes, Bob takes 10, Candace takes 20 minutes, and Dave 25. How do they get across?&lt;/p&gt; 
&lt;/blockquote&gt; 
 
&lt;p&gt;I&amp;#8217;m not interested in the answer&amp;#8212;I&amp;#8217;m interviewing programmers, not law school applicants&amp;#8212;but rather in how to write a program to find the answer.&lt;/p&gt; 
 
&lt;p&gt;The basic shape of the solution is to represent the state of the world (where are the people, where is the flashlight, how much battery is left), write a function to compute from any particular state the set of possible next states, then search for an answer (a path from the start state to the final state) in the tree formed by applying the next state function transitively to the start state. (&lt;a href='http://web.engr.oregonstate.edu/~erwig/papers/Zurg_JFP04.pdf'&gt;Here is a paper&lt;/a&gt; describing solutions in Prolog and Haskell.)&lt;/p&gt; 
 
&lt;p&gt;Here is a first solution in Scala:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Bridge0&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;Person&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Enumeration&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;Person&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Value&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Alice&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Bob&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Candace&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Dave&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Value&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;all&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Alice&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Bob&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Candace&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Dave&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='c1'&gt;// values is broken&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;Person._&lt;/span&gt; 
 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;times&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Alice&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;5&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Bob&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;10&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Candace&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;20&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Dave&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;25&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; 
                   &lt;span class='n'&gt;lightOnLeft&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
                   &lt;span class='n'&gt;timeRemaining&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We define an enumeration of people (the &lt;code&gt;Enumeration&lt;/code&gt; class is a &lt;a href='https://lampsvn.epfl.ch/trac/scala/ticket/3687'&gt;bit broken&lt;/a&gt; in Scala 2.8.1), a map of the time each takes to cross, and a case class to store the state of the world: the list of people on the left side of the bridge (the right side is just the complement); whether the flashlight is on the left; and how much time remains in the flashlight.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;,&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;, &lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
    &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foldLeft&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pairs&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
      &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foldLeft&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pairs&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;pairs&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;pairs&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;pairs&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This function returns the list of pairs of people from the input list. We use &lt;code&gt;foldLeft&lt;/code&gt; to do a double loop over the input list, accumulating pairs &lt;code&gt;(p1, p2)&lt;/code&gt; where &lt;code&gt;p1 &amp;lt; p2&lt;/code&gt;; this avoids returning &lt;code&gt;(Alice, Bob)&lt;/code&gt; and also &lt;code&gt;(Bob, Alice)&lt;/code&gt;. The use of &lt;code&gt;foldLeft&lt;/code&gt; is rather OCamlish, and if you know Scala you will complain that &lt;code&gt;foldLeft&lt;/code&gt; is not idiomatic&amp;#8212;we will repair this shortly.&lt;/p&gt; 
 
&lt;p&gt;In Scala, &lt;code&gt;Nil&lt;/code&gt; doesn&amp;#8217;t have type &lt;code&gt;&amp;#39;a list&lt;/code&gt; like in OCaml and Haskell, but rather &lt;code&gt;List[Nothing]&lt;/code&gt;. The way local type inference works, the type variable in the type of &lt;code&gt;foldLeft&lt;/code&gt; is instantiated with the type of the &lt;code&gt;init&lt;/code&gt; argument, so you have to ascribe a type to &lt;code&gt;init&lt;/code&gt; (or explicitly instantiate the type variable with &lt;code&gt;foldLeft[List[(Person,
Person)]]&lt;/code&gt;) or else you get a type clash between &lt;code&gt;List[Nothing]&lt;/code&gt; and &lt;code&gt;List[(Person, Person)]&lt;/code&gt;.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;next&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lightOnLeft&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
      &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;foldLeft&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;states&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
            &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='n'&gt;math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;max&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
          &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
            &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
              &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filterNot&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
            &lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;states&lt;/span&gt; 
          &lt;span class='o'&gt;}&lt;/span&gt; 
          &lt;span class='k'&gt;else&lt;/span&gt; 
            &lt;span class='n'&gt;states&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;right&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filterNot&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;contains&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
      &lt;span class='n'&gt;right&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foldLeft&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;init&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;states&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;states&lt;/span&gt; 
        &lt;span class='k'&gt;else&lt;/span&gt; 
          &lt;span class='n'&gt;states&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Here we compute the set of successor states for a state. We make a heuristic simplification: when the flashlight is on the left (the side where everyone begins) we move two people from the left to the right; when it is on the right we move only one. I don&amp;#8217;t have a proof that an answer must take this form, but I believe it, and it makes the code shorter.&lt;/p&gt; 
 
&lt;p&gt;So when the light is on the left we fold over all the pairs of people still on the left, compute the time remaining if they were to cross, and if it is not negative build a new state where they and the flashlight are moved to the right and the time remaining updated.&lt;/p&gt; 
 
&lt;p&gt;If the light is on the right we do the same in reverse, but choose only one person to move.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;next&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt; 
      &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;)).&lt;/span&gt; 
        &lt;span class='n'&gt;foldLeft&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='o'&gt;++&lt;/span&gt; &lt;span class='k'&gt;_&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;search&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;_&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A list of successive states is a &lt;em&gt;path&lt;/em&gt; (with the starting state at the end and the most recent state at the beginning); the state tree is a set of paths. The tree rooted at a path is the set of paths with the input path as a suffix. To compute this tree, we find the successor states of the head of the path, augment the path with each state in turn, recursively find the tree rooted at each augmented path, then append them all (including the input path).&lt;/p&gt; 
 
&lt;p&gt;Then to find an answer, we generate the state tree rooted at the path consisting only of the start state (everybody and the flashlight on the left, 60 minutes remaining on the light), then filter out the paths which end in a final state (everybody on the right).&lt;/p&gt; 
&lt;b&gt;For-comprehensions&lt;/b&gt; 
&lt;p&gt;To make the code above more idiomatic Scala (and more readable), we would of course use for-comprehensions, for example:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;,&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Just as before, we do a double loop over the input list, returning pairs where &lt;code&gt;p1 &amp;lt; p2&lt;/code&gt;. (However, under the hood the result list is constructed by appending to a &lt;code&gt;ListBuffer&lt;/code&gt; rather than with &lt;code&gt;::&lt;/code&gt;, so the pairs are returned in the reverse order.)&lt;/p&gt; 
 
&lt;p&gt;The for-comprehension syntax isn&amp;#8217;t specific to lists. It&amp;#8217;s syntactic sugar which translates to method calls, so we can use it on any objects which implement the right methods. The methods we need are&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;withFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;where &lt;code&gt;T&lt;/code&gt; is some type constructor, like &lt;code&gt;List&lt;/code&gt;. For &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt; and &lt;code&gt;map&lt;/code&gt; have their ordinary meaning, and &lt;code&gt;flatMap&lt;/code&gt; is a &lt;code&gt;map&lt;/code&gt; (where the result type must be a list) which concatenates the resulting lists (that is, it flattens the list of lists).&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;WithFilter&lt;/code&gt; is like &lt;code&gt;filter&lt;/code&gt; but should be implemented as a &amp;#8220;virtual&amp;#8221; filter for efficiency&amp;#8212;for &lt;code&gt;List&lt;/code&gt; it doesn&amp;#8217;t build a new filtered list, but instead just keeps track of the filter function; this way multiple adjacent filters can be combined and the result produced with a single pass over the list.&lt;/p&gt; 
 
&lt;p&gt;The details of the translation are in the &lt;a href='http://www.scala-lang.org/docu/files/ScalaReference.pdf'&gt;Scala reference manual&lt;/a&gt;, section 6.19. Roughly speaking, &lt;code&gt;&amp;lt;-&lt;/code&gt; becomes &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt; becomes &lt;code&gt;filter&lt;/code&gt;, and &lt;code&gt;yield&lt;/code&gt; becomes &lt;code&gt;map&lt;/code&gt;. So another way to write &lt;code&gt;chooseTwo&lt;/code&gt; is:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;,&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
      &lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;).&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)))&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt;&lt;b&gt;The logic monad&lt;/b&gt; 
&lt;p&gt;So far we have taken a concrete view of the choices that arise in searching the state tree, by representing a choice among alternatives as a list. For example, in the &lt;code&gt;chooseTwo&lt;/code&gt; function we returned a list of alternative pairs. I want now to take a more abstract view, and define an abstract type &lt;code&gt;T[A]&lt;/code&gt; to represent a choice among alternatives of type &lt;code&gt;A&lt;/code&gt;, along with operations on the type, packaged into a trait:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A &lt;code&gt;fail&lt;/code&gt; value is a choice among no alternatives. A &lt;code&gt;unit(a)&lt;/code&gt; is a choice of a single alternative. The value &lt;code&gt;or(t1, t2)&lt;/code&gt; is a choice among the alternatives represented by &lt;code&gt;t1&lt;/code&gt; together with the alternatives represented by &lt;code&gt;t2&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;The meaning of &lt;code&gt;apply&lt;/code&gt;ing a function to a choice of alternatives is a choice among the results of applying the function to each alternative; that is, if &lt;code&gt;t&lt;/code&gt; represents a choice among &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;3&lt;/code&gt;, then &lt;code&gt;apply(t, f)&lt;/code&gt; represents a choice among &lt;code&gt;f(1)&lt;/code&gt;, &lt;code&gt;f(2)&lt;/code&gt;, and &lt;code&gt;f(3)&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;Bind&lt;/code&gt; is the same except the function returns a choice of alternatives, so we must combine all the alternatives in the result; that is, if &lt;code&gt;t&lt;/code&gt; is a choice among &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, and &lt;code&gt;5&lt;/code&gt;, and &lt;code&gt;f&lt;/code&gt; is &lt;code&gt;{ x =&amp;gt; or(unit(x), unit(x + 1)) }&lt;/code&gt;, then &lt;code&gt;bind(t, f)&lt;/code&gt; is a choice among &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;5&lt;/code&gt;, and &lt;code&gt;6&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;A &lt;code&gt;filter&lt;/code&gt; of a choice of alternatives by a predicate is a choice among only the alternatives which pass the the predicate.&lt;/p&gt; 
 
&lt;p&gt;Finally, &lt;code&gt;split&lt;/code&gt; is a function which returns the first alternative in a choice of alternatives (if there is at least one) along with a choice among the remaining alternatives.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;as&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;as&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;foldRight&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; 
      &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
        &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;As a convenience, &lt;code&gt;or(as: List[A])&lt;/code&gt; means a choice among the elements of &lt;code&gt;as&lt;/code&gt;. And &lt;code&gt;run&lt;/code&gt; returns a list of the first &lt;code&gt;n&lt;/code&gt; alternatives in a choice, picking them off one by one with &lt;code&gt;split&lt;/code&gt;; this is how we get answers out of a &lt;code&gt;T[A]&lt;/code&gt;.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Syntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;withFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
    &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='o'&gt;|(&lt;/span&gt;&lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;implicit&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;syntax&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Syntax&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Here we hook into the for-comprehension notation, by wrapping values of type &lt;code&gt;T[A]&lt;/code&gt; in an object with the methods we need (and &lt;code&gt;|&lt;/code&gt; as an additional bit of syntactic sugar), which methods just delegate to the functions defined above. We arrange with an implicit conversion for these wrappers to spring into existence when we need them.&lt;/p&gt; 
&lt;b&gt;The bridge puzzle with the logic monad&lt;/b&gt; 
&lt;p&gt;Now we can rewrite the solution in terms of the &lt;code&gt;Logic&lt;/code&gt; trait:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Bridge&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;import&lt;/span&gt; &lt;span class='nn'&gt;Logic._&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We pass an implementation of the logic monad in, then open it so the implicit conversion is available (we can also use &lt;code&gt;T[A]&lt;/code&gt; and the &lt;code&gt;Logic&lt;/code&gt; functions without qualification).&lt;/p&gt; 
 
&lt;p&gt;The &lt;code&gt;Person&lt;/code&gt;, &lt;code&gt;times&lt;/code&gt;, and &lt;code&gt;State&lt;/code&gt; definitions are as before.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;Person&lt;/span&gt;,&lt;span class='kt'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;)]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;list&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;As we saw, we can write &lt;code&gt;chooseTwo&lt;/code&gt; more straightforwardly using a for-comprehension. In the previous version we punned on &lt;code&gt;list&lt;/code&gt; as a concrete list and as a choice among alternatives; here we convert one to the other explicitly.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;next&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lightOnLeft&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;chooseTwo&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
          &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='n'&gt;math&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;max&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p1&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; &lt;span class='n'&gt;times&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p2&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
        &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
          &lt;span class='n'&gt;state&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filterNot&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;p1&lt;/span&gt; &lt;span class='o'&gt;||&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;p2&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
        &lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;false&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;timeRemaining&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='c1'&gt;// ...&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This is pretty much as before, except with for-comprehensions instead of &lt;code&gt;foldLeft&lt;/code&gt; and explicit consing. (You can easily figure out the branch for the flashlight on the right.)&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;private&lt;/span&gt; &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
         &lt;span class='n'&gt;state&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;next&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
         &lt;span class='n'&gt;path&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;state&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
       &lt;span class='o'&gt;}&lt;/span&gt; &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;search&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
      &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt; 
    &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;In &lt;code&gt;tree&lt;/code&gt; we use &lt;code&gt;|&lt;/code&gt; to adjoin the input path (previously we gave it in the initial value of &lt;code&gt;foldLeft&lt;/code&gt;). In &lt;code&gt;search&lt;/code&gt; we need to actually run the &lt;code&gt;Logic.T[A]&lt;/code&gt; value rather than returning it, because it&amp;#8217;s an abstract type and can&amp;#8217;t escape the module (see the Postscript for an alternative); this is why the other methods must be &lt;code&gt;private&lt;/code&gt;.&lt;/p&gt; 
&lt;b&gt;Implementing the logic monad with lists&lt;/b&gt; 
&lt;p&gt;We can recover the original solution by implementing &lt;code&gt;Logic&lt;/code&gt; with lists:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;object&lt;/span&gt; &lt;span class='nc'&gt;LogicList&lt;/span&gt; &lt;span class='k'&gt;extends&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;fail&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;unit&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;or&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t1&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t1&lt;/span&gt; &lt;span class='o'&gt;:::&lt;/span&gt; &lt;span class='n'&gt;t2&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;apply&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;bind&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
      &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
    &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A choice among alternatives is just a &lt;code&gt;List&lt;/code&gt; of the alternatives, so the semantics we sketched above are realized in a very direct way.&lt;/p&gt; 
 
&lt;p&gt;The downside to the &lt;code&gt;List&lt;/code&gt; implementation is that we compute all the alternatives, even if we only care about one of them. (In the bridge problem any path to the final state is a satisfactory answer, but our program computes all such paths, even if we pass an argument to &lt;code&gt;search&lt;/code&gt; requesting only one answer.) We might even want to solve problems with an infinite number of solutions.&lt;/p&gt; 
 
&lt;p&gt;Next time we&amp;#8217;ll repair this downside by implementing the backtracking monad from the paper by Kiselyov et al.&lt;/p&gt; 
 
&lt;p&gt;See the complete code &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/scala-logic'&gt;here&lt;/a&gt;.&lt;/p&gt; 
&lt;b&gt;Postscript: modules in Scala&lt;/b&gt; 
&lt;p&gt;I got the idea of implementing the for-comprehension methods as an implict wrapper from Edward Kmett&amp;#8217;s &lt;a href='https://github.com/ekmett/functorial'&gt;functorial&lt;/a&gt; library. It&amp;#8217;s nice that &lt;code&gt;T[A]&lt;/code&gt; remains completely abstract, and the for-comprehension notation is just sugar. I also tried an implementation where &lt;code&gt;T[A]&lt;/code&gt; is bounded by a trait containing the methods:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Monadic&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;, &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;B&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;flatMap&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;B&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;withFilter&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;A&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Boolean&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='o'&gt;|(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;split&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Option&lt;/span&gt;&lt;span class='o'&gt;[(&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;,&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;])]&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
 
&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;:&lt;/span&gt; &lt;span class='nc'&gt;Monadic&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;T&lt;/span&gt;, &lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='c1'&gt;// no Syntax class needed&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This works too but the type system hackery is a bit ugly, and it constrains implementations of &lt;code&gt;Logic&lt;/code&gt; more than is necessary.&lt;/p&gt; 
 
&lt;p&gt;Another design choice is whether &lt;code&gt;T[A]&lt;/code&gt; is an abstract type (as I have it) or a type parameter of &lt;code&gt;Logic&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;trait&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='k'&gt;_&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;L&lt;/span&gt; &lt;span class='k'&gt;=&amp;gt;&lt;/span&gt; 
  &lt;span class='c1'&gt;// no abstract type T[A] but otherwise as before&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Neither alternative provides the expressivity of OCaml modules (&lt;em&gt;but see addendum below&lt;/em&gt;): with abstract types, consumers of &lt;code&gt;Logic&lt;/code&gt; cannot return values of &lt;code&gt;T[A]&lt;/code&gt; (as we saw above); with a type parameter, they can, but the type is no longer abstract.&lt;/p&gt; 
 
&lt;p&gt;In OCaml we would write&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
&lt;span class='k'&gt;sig&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='c'&gt;(* and so on *)&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
 
&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Bridge&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;L&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
&lt;span class='k'&gt;struct&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;state&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;...&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;search&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;state&lt;/span&gt; &lt;span class='kt'&gt;list&lt;/span&gt; &lt;span class='nn'&gt;L&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;and get both the abstract type and the ability to return values of the type.&lt;/p&gt; 
 
&lt;p&gt;&lt;em&gt;Addendum&lt;/em&gt;&lt;/p&gt; 
 
&lt;p&gt;Jorge Ortiz points out in the comments that it is possible to keep &lt;code&gt;T[A]&lt;/code&gt; abstract and also return its values from &lt;code&gt;Bridge&lt;/code&gt;, by making the &lt;code&gt;Logic&lt;/code&gt; argument a (public) &lt;code&gt;val&lt;/code&gt;. We can then remove the &lt;code&gt;private&lt;/code&gt;s, and write &lt;code&gt;search&lt;/code&gt; as just:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;search&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;List&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;State&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Person&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;all&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='kc'&gt;true&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;60&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='k'&gt;for&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;tree&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;start&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;head&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;left&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='nc'&gt;Nil&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
    &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='n'&gt;path&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;instead of baking &lt;code&gt;run&lt;/code&gt; into it. Now, if we write &lt;code&gt;val b = new Bridge(LogicList)&lt;/code&gt; then &lt;code&gt;b.search&lt;/code&gt; has type &lt;code&gt;b.Logic.T[List[b.State]]&lt;/code&gt;, and we can call &lt;code&gt;b.Logic.run&lt;/code&gt; to evaluate it.&lt;/p&gt; 
 
&lt;p&gt;This is only a modest improvement; what&amp;#8217;s still missing, compared to the OCaml version, is the fact that &lt;code&gt;LogicList&lt;/code&gt; and &lt;code&gt;b.Logic&lt;/code&gt; are the same module. So we can&amp;#8217;t call &lt;code&gt;LogicList.run(b.search)&lt;/code&gt; directly. Worse, we can&amp;#8217;t compose modules which use the same &lt;code&gt;Logic&lt;/code&gt; implementation, because they each have their own incompatibly-typed &lt;code&gt;Logic&lt;/code&gt; member.&lt;/p&gt; 
 
&lt;p&gt;I thought there might be a way out of this using singleton types&amp;#8212;the idea is that a match of a value &lt;code&gt;v&lt;/code&gt; against a typed pattern where the type is &lt;code&gt;w.type&lt;/code&gt; succeeds when &lt;code&gt;v eq w&lt;/code&gt; (section 8.2 in the reference manual). So we can define&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt; 
  &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
  &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Bridge&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; 
  &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;b.Logic.T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;],&lt;/span&gt; 
  &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Int&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;A&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; 
&lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='nc'&gt;Logic&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
    &lt;span class='k'&gt;case&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;b.Logic.&lt;/span&gt;&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='o'&gt;}&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;which is accepted, but sadly&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='n'&gt;scala&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;b.State&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt;&lt;span class='nc'&gt;LogicList&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;search&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='o'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;console&lt;/span&gt;&lt;span class='o'&gt;&amp;gt;:&lt;/span&gt;&lt;span class='mi'&gt;8&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;error:&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='kt'&gt;mismatch&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
 &lt;span class='n'&gt;found&lt;/span&gt;   &lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;b.Logic.T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;b.State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
 &lt;span class='n'&gt;required&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;b.Logic.T&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;b.State&lt;/span&gt;&lt;span class='o'&gt;]]&lt;/span&gt; 
       &lt;span class='n'&gt;run&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;List&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;b.State&lt;/span&gt;&lt;span class='o'&gt;]](&lt;/span&gt;&lt;span class='nc'&gt;LogicList&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;search&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
                                          &lt;span class='o'&gt;^&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;em&gt;Addendum addendum&lt;/em&gt;&lt;/p&gt; 
 
&lt;p&gt;Some further advice from Jorge Ortiz: the specific type of &lt;code&gt;Logic&lt;/code&gt; (not just &lt;code&gt;Logic.type&lt;/code&gt;) can be exposed outside &lt;code&gt;Bridge&lt;/code&gt; either through polymorphism:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Bridge&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='kt'&gt;L&lt;/span&gt; &lt;span class='k'&gt;&amp;lt;:&lt;/span&gt; &lt;span class='kt'&gt;Logic&lt;/span&gt;&lt;span class='o'&gt;](&lt;/span&gt;&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;L&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
 
&lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='k'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='nc'&gt;Bridge&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;LogicList&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;or by defining an abstract value (this works the same if &lt;code&gt;Bridge&lt;/code&gt; is a trait):&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='scala'&gt;&lt;span class='k'&gt;abstract&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Bridge&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='nc'&gt;Logic&lt;/span&gt;&lt;span class='k'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;Logic&lt;/span&gt; 
  &lt;span class='o'&gt;...&lt;/span&gt; 
&lt;span class='o'&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;So we can compose uses of &lt;code&gt;T&lt;/code&gt; but it remains abstract.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-3020455680296288063?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/3020455680296288063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-1.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/3020455680296288063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/3020455680296288063'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-1.html' title='Logic programming in Scala, part 1'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-6031969833616018203</id><published>2010-11-24T20:58:00.000-08:00</published><updated>2010-11-24T20:58:10.608-08:00</updated><title type='text'>Three uses for a binary heap</title><content type='html'>&lt;p&gt;Lately I have been interviewing for jobs, so doing a lot of whiteboard programming, and &lt;a href='http://en.wikipedia.org/wiki/Binary_heap'&gt;binary heaps&lt;/a&gt; keep arising in the solutions to these interview problems. There is nothing new or remarkable about these applications (binary heaps and their uses are covered in any undergraduate algorithms class), but I thought I would write them down because they are cute, and in the hope that they might be useful to someone else who (like me) gets by most days as a working programmer with no algorithm fancier than quicksort or binary search.&lt;/p&gt; 
&lt;b&gt;Binary heaps&lt;/b&gt; 
&lt;p&gt;Here&amp;#8217;s a signature for a binary heap module &lt;code&gt;Heap&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;OrderedType&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
&lt;span class='k'&gt;sig&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
 
&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;S&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='n'&gt;option&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
 
&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Make&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;O&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;OrderedType&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;S&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;O&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We start with a signature for ordered types (following the &lt;code&gt;Set&lt;/code&gt; and &lt;code&gt;Map&lt;/code&gt; modules in the standard library), so we can provide a type-specific comparison function.&lt;/p&gt; 
 
&lt;p&gt;From an ordered type we can make a heap which supports adding elements, peeking the smallest element (&lt;code&gt;None&lt;/code&gt; if there are no elements) without removing it, removing and returning the smallest element (raising &lt;code&gt;Not_found&lt;/code&gt; if the heap is empty), and returning the number of elements.&lt;/p&gt; 
 
&lt;p&gt;We&amp;#8217;ll work out the asymptotic running times of the algorithms below, so it will be useful to know that the worst-case running time of the &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;take_min&lt;/code&gt; functions is &lt;code&gt;O(log n)&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the number of elements in the heap.&lt;/p&gt; 
&lt;b&gt;Finding the k smallest elements in a list&lt;/b&gt; 
&lt;p&gt;Here&amp;#8217;s a simple one. To find the smallest element in a list, we could sort the list then take the first element in the sorted list, at a cost of &lt;code&gt;O(log n)&lt;/code&gt;. Or we could just take a pass over the list keeping a running minimum, at a cost of &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;What if we want the &lt;code&gt;k&lt;/code&gt; smallest elements? Again, we could sort the list, but if &lt;code&gt;k &amp;lt; n&lt;/code&gt; we can do better by generalizing the single-pass solution. The idea is to keep the &lt;code&gt;k&lt;/code&gt; smallest elements we&amp;#8217;ve seen so far in a binary heap. For each element in the list we add it to the heap, then (if there were already &lt;code&gt;k&lt;/code&gt; elements in the heap) remove the largest element in the heap, leaving the &lt;code&gt;k&lt;/code&gt; smallest.&lt;/p&gt; 
 
&lt;p&gt;The running time is &lt;code&gt;O(n log k)&lt;/code&gt; since we do an &lt;code&gt;add&lt;/code&gt; and a &lt;code&gt;take_min&lt;/code&gt; in a heap of size &lt;code&gt;k&lt;/code&gt; for each of &lt;code&gt;n&lt;/code&gt; elements in the list. Here&amp;#8217;s the code:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;kmin&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;OT&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;H&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Heap&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Make&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;OT&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;iter&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
       &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
       &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; 
       &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='n'&gt;ignore&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='n'&gt;mins&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;mins&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;mins&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Here we make good use of OCaml 3.12&amp;#8217;s new feature for &lt;a href='http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc80'&gt;explicitly naming type variables&lt;/a&gt; in a polymorphic function to make a structure matching &lt;code&gt;OrderedType&lt;/code&gt;. The heap has the same element type as the list, but we reverse the comparison since we want to remove the largest rather than smallest element from the heap in the loop. At the end of &lt;code&gt;kmin&lt;/code&gt; we drain the heap to build a list of the &lt;code&gt;k&lt;/code&gt; smallest elements.&lt;/p&gt; 
&lt;b&gt;Merging k lists&lt;/b&gt; 
&lt;p&gt;Suppose we want to merge &lt;code&gt;k&lt;/code&gt; lists. We could merge them pairwise until there is only one list, but that would take &lt;code&gt;k - 1&lt;/code&gt; passes, for a worst-case running time of &lt;code&gt;O(n * (k - 1))&lt;/code&gt;. Instead we can merge them all in one pass, using a binary heap so we can find the next smallest element of &lt;code&gt;k&lt;/code&gt; lists in &lt;code&gt;O(log k)&lt;/code&gt; time, for a running time of &lt;code&gt;O(n
log k)&lt;/code&gt;. Here&amp;#8217;s the code:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;merge&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;ls&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;OT&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='kt'&gt;list&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;hd&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;H&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Heap&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Make&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;OT&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;iter&lt;/span&gt; &lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;ls&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;H&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                &lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
                &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We store the lists in the heap, and compare them by comparing their head element (we&amp;#8217;re careful not to put an empty list in the heap). When we take the smallest list from the heap, its head becomes the next element in the output list, and we return its tail (if it is not empty) to the heap.&lt;/p&gt; 
&lt;b&gt;Computing a skyline&lt;/b&gt; 
&lt;p&gt;The next problem was told to me in terms of computing the skyline of a set of buildings. A building has a height and a starting and ending &lt;code&gt;x&lt;/code&gt;-coordinate; buildings may overlap. The skyline of a set of buildings is a list of (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;) pairs (in ascending &lt;code&gt;x&lt;/code&gt; order), describing a sequence of horizontal line segments (each starting at (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;) and ending at the subsequent &lt;code&gt;x&lt;/code&gt;), such that at any &lt;code&gt;x&lt;/code&gt; there is no space between the line segment and the tallest building. (Here&amp;#8217;s &lt;a href='http://stackoverflow.com/questions/1066234/the-skyline-problem'&gt;another description&lt;/a&gt; with diagrams.)&lt;/p&gt; 
 
&lt;p&gt;I googled a bit to see what this is useful for, and didn&amp;#8217;t find much. One application is to extract a monophonic line from polyphonic music, where &lt;code&gt;x&lt;/code&gt; is time and height is some metric on notes, like pitch or volume. It might be useful for searching data which is only intermittently applicable&amp;#8212;say, to compute a schedule over time of the nearest open restaurant.&lt;/p&gt; 
 
&lt;p&gt;The algorithm scans the building start and end points in ascending &lt;code&gt;x&lt;/code&gt; order, keeping the &amp;#8220;active&amp;#8221; buildings (those which overlap the current &lt;code&gt;x&lt;/code&gt;) in a binary heap. The height of the skyline can only change at a building start or end point. We can determine the tallest building at a point by calling &lt;code&gt;peek_min&lt;/code&gt; on the heap.&lt;/p&gt; 
 
&lt;p&gt;When we hit a start point we add the building to the heap; for an end point we do nothing (the heap has no operation to remove an element). So we may have inactive buildings in the heap. We remove them lazily&amp;#8212;before checking the height of the highest building, we call &lt;code&gt;take_min&lt;/code&gt; to remove any higher inactive buildings.&lt;/p&gt; 
 
&lt;p&gt;The worst-case running time is &lt;code&gt;O(n log n)&lt;/code&gt;, since we do some heap operations for each building, and we might end up with all the buildings in the heap.&lt;/p&gt; 
 
&lt;p&gt;Here&amp;#8217;s the code:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;building&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='c'&gt;(* x0, x1, h *)&lt;/span&gt; 
 
&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;skyline&lt;/span&gt; &lt;span class='n'&gt;bs&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;OT&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;building&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;_)&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x2&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;_)&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;x1&lt;/span&gt; &lt;span class='n'&gt;x2&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Events&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Heap&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Make&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;OT&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;events&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Events&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;iter&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='n'&gt;x0&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='n'&gt;x1&lt;/span&gt;&lt;span class='o'&gt;,_)&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
       &lt;span class='nn'&gt;Events&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;events&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x0&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; 
       &lt;span class='nn'&gt;Events&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;events&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x1&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
    &lt;span class='n'&gt;bs&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;OT&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;building&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='o'&gt;(_,_,&lt;/span&gt;&lt;span class='n'&gt;h1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;(_,_,&lt;/span&gt;&lt;span class='n'&gt;h2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h2&lt;/span&gt; &lt;span class='n'&gt;h1&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Heights&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Heap&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Make&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;OT&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;heights&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Heights&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='n'&gt;last&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;Events&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;events&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x0&lt;/span&gt;&lt;span class='o'&gt;,_,&lt;/span&gt;&lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Events&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;events&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;x0&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='nn'&gt;Heights&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;heights&lt;/span&gt; &lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='k'&gt;while&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;Heights&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;heights&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
                   &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(_,&lt;/span&gt;&lt;span class='n'&gt;x1&lt;/span&gt;&lt;span class='o'&gt;,_)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;x1&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;=&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; 
                   &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; 
            &lt;span class='n'&gt;ignore&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Heights&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;heights&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='k'&gt;done&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
            &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;Heights&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;heights&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
              &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(_,_,&lt;/span&gt;&lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; 
              &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;last&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;h&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;h&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='n'&gt;last&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt; &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
  &lt;span class='n'&gt;loop&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We use a second heap &lt;code&gt;events&lt;/code&gt; to store the &amp;#8220;events&amp;#8221; (the start and end points of all the buildings), in order to process them in ascending &lt;code&gt;x&lt;/code&gt; order. (This use is not dynamic&amp;#8212;we do not add new elements to the heap while processing them&amp;#8212;so we could just as well use another means of sorting the points.) In this heap we store the &lt;code&gt;x&lt;/code&gt; coordinate and the building (we can tell whether we have a start or end point by comparing the &lt;code&gt;x&lt;/code&gt; coordinate to the building&amp;#8217;s start point), and compare elements by comparing just the &lt;code&gt;x&lt;/code&gt; coordinates.&lt;/p&gt; 
 
&lt;p&gt;The main heap &lt;code&gt;heights&lt;/code&gt; stores buildings, and we compare them by comparing heights (reversed, so &lt;code&gt;peek_min&lt;/code&gt; peeks the tallest building). While there are still events, we add the building to &lt;code&gt;heights&lt;/code&gt; if the event is a start point, clear out inactive buildings, then return the pair (&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;) where &lt;code&gt;x&lt;/code&gt; is the point we&amp;#8217;re processing and &lt;code&gt;y&lt;/code&gt; is the height of the tallest active building. Additionally we filter out adjacent pairs with the same height; these can arise when a shorter building starts or ends while a taller building is active.&lt;/p&gt; 
&lt;b&gt;Implementing binary heaps&lt;/b&gt; 
&lt;p&gt;The following implementation is derived from the one in Daniel Bünzli&amp;#8217;s &lt;a href='http://erratique.ch/software/react'&gt;React&lt;/a&gt; library (edited a little bit for readability). The &lt;a href='http://en.wikipedia.org/wiki/Binary_heap'&gt;Wikipedia article on binary heaps&lt;/a&gt; explains the standard technique well, so I won&amp;#8217;t repeat it.&lt;/p&gt; 
 
&lt;p&gt;The only piece of trickiness is the use of &lt;code&gt;Obj.magic 0&lt;/code&gt; for unused elements of the array, so we can grow it by doubling the size rather than adding a single element each time, and thereby amortize the cost of blitting the old array.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Make&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;O&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;OrderedType&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;S&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;O&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
&lt;span class='k'&gt;struct&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;O&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='k'&gt;mutable&lt;/span&gt; &lt;span class='n'&gt;arr&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;elt&lt;/span&gt; &lt;span class='kt'&gt;array&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='k'&gt;mutable&lt;/span&gt; &lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;int&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='n'&gt;arr&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;[||];&lt;/span&gt; &lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i1&lt;/span&gt; &lt;span class='n'&gt;i2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;O&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;swap&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i1&lt;/span&gt; &lt;span class='n'&gt;i2&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i2&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; 
    &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;i2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;up&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='k'&gt;else&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;/&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; 
        &lt;span class='n'&gt;swap&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
        &lt;span class='n'&gt;up&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; 
      &lt;span class='k'&gt;end&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;down&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='k'&gt;else&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;child&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
        &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; 
        &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;else&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;compare&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='n'&gt;child&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; 
        &lt;span class='n'&gt;swap&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;i&lt;/span&gt; &lt;span class='n'&gt;child&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
        &lt;span class='n'&gt;down&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;child&lt;/span&gt; 
      &lt;span class='k'&gt;end&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;add&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;if&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;length&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt; 
    &lt;span class='k'&gt;then&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='mi'&gt;2&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;arr&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make&lt;/span&gt; &lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Obj&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;magic&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='nn'&gt;Array&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;blit&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='n'&gt;arr&amp;#39;&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;arr&amp;#39;&lt;/span&gt; 
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='n'&gt;up&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;peek_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;take_min&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;raise&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Obj&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;magic&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; 
          &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='n'&gt;m&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;m&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;-&lt;/span&gt; &lt;span class='mi'&gt;1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; 
          &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;arr&lt;/span&gt;&lt;span class='o'&gt;.(&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Obj&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;magic&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;);&lt;/span&gt; 
          &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;-&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='n'&gt;down&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='n'&gt;m&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;size&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;len&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;(Complete code is &lt;a href='https://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/binary-heaps'&gt;here&lt;/a&gt;.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-6031969833616018203?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/6031969833616018203/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/11/three-uses-for-binary-heap.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/6031969833616018203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/6031969833616018203'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/11/three-uses-for-binary-heap.html' title='Three uses for a binary heap'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-2352334798898086638</id><published>2010-09-10T17:16:00.000-07:00</published><updated>2010-09-13T10:55:05.949-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camlp4'/><title type='text'>Reading Camlp4, part 11: syntax extensions</title><content type='html'>&lt;p&gt;In this final (?) post in my series on Camlp4, I want at last to cover syntax extensions. A nontrivial syntax extension involves almost all the topics we have &lt;a href='/p/reading-camlp4.html'&gt;previously covered&lt;/a&gt;, so it seems fitting that we treat them last.&lt;/p&gt; 
&lt;b&gt;Extending grammars&lt;/b&gt; 
&lt;p&gt;In the post on &lt;a href='/2010/05/reading-camlp4-part-6-parsing.html'&gt;parsing&lt;/a&gt; we covered Camlp4 grammars but stopped short of explaining how to extend them. Well, this is not completely true: we used the &lt;code&gt;EXTEND&lt;/code&gt; form to extend an empty grammar, and we can also use it to extend non-empty grammars. We saw a small example of this when implementing &lt;a href='/2010/08/reading-camlp4-part-8-implementing.html'&gt;quotations&lt;/a&gt;, where we extended the JSON grammar with a new &lt;code&gt;json_eoi&lt;/code&gt; entry (which refered to an entry in the original grammar). Rules and levels may also be added to existing entries, and rules may be deleted.&lt;/p&gt; 
 
&lt;p&gt;Let&amp;#8217;s look at a complete syntax extension, which demonstrates modifying Camlp4&amp;#8217;s OCaml grammar. The purpose of the extension is to change the precedence of the method call operator &lt;code&gt;#&lt;/code&gt; to make &amp;#8220;method chaining&amp;#8221; read better. For example, if the &lt;code&gt;foo&lt;/code&gt; method returns an object, you can write&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='n'&gt;obj&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;foo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;baz&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;to call the &lt;code&gt;baz&lt;/code&gt; method, rather than needing&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;obj&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;foo&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;)#&lt;/span&gt;&lt;span class='n'&gt;baz&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;(I originally wrote this for use with the &lt;a href='http://github.com/jaked/ocamljs/tree/master/src/jquery/'&gt;&lt;code&gt;jQuery&lt;/code&gt; binding for &lt;code&gt;ocamljs&lt;/code&gt;&lt;/a&gt;; method chaining is common with &lt;code&gt;jQuery&lt;/code&gt;.)&lt;/p&gt; 
 
&lt;p&gt;Here is the extension:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;open&lt;/span&gt; &lt;span class='nc'&gt;Camlp4&lt;/span&gt; 
  
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Id&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nn'&gt;Sig&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;name&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;pa_jquery&amp;quot;&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;version&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;0.1&amp;quot;&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
  
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Make&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Syntax&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nn'&gt;Sig&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Camlp4Syntax&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;open&lt;/span&gt; &lt;span class='nc'&gt;Sig&lt;/span&gt; 
    &lt;span class='k'&gt;include&lt;/span&gt; &lt;span class='nc'&gt;Syntax&lt;/span&gt; 
  
    &lt;span class='nc'&gt;DELETE_RULE&lt;/span&gt; &lt;span class='nc'&gt;Gram&lt;/span&gt; &lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;SELF&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='nc'&gt;END&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  
    &lt;span class='nc'&gt;EXTEND&lt;/span&gt; &lt;span class='nc'&gt;Gram&lt;/span&gt; 
      &lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;BEFORE&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;apply&amp;quot;&lt;/span&gt; 
        &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;#&amp;quot;&lt;/span&gt; &lt;span class='nc'&gt;LEFTA&lt;/span&gt; 
          &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;SELF&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;#&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;lab&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;label&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
              &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;#&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;lab&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; 
        &lt;span class='o'&gt;];&lt;/span&gt; 
    &lt;span class='nc'&gt;END&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
  
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;M&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Register&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;OCamlSyntaxExtension&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Id&lt;/span&gt;&lt;span class='o'&gt;)(&lt;/span&gt;&lt;span class='nc'&gt;Make&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;To make sense of a syntax extension it&amp;#8217;s helpful to refer to &lt;code&gt;Camlp4OCamlRevisedParser.ml&lt;/code&gt; (which defines the revised syntax grammar) and &lt;code&gt;Camlp4OCamlParser.ml&lt;/code&gt; (which defines the original syntax as an extension of the revised syntax). There we see that the &lt;code&gt;#&lt;/code&gt; operator is parsed in the &lt;code&gt;expr&lt;/code&gt; entry, in a level called &amp;#8221;&lt;code&gt;.&lt;/code&gt;&amp;#8221; (which includes other dereferencing operators), and that this level appears below the &lt;code&gt;apply&lt;/code&gt; level, which parses function application. Recall from the &lt;a href='/2010/05/reading-camlp4-part-6-parsing.html'&gt;parsing&lt;/a&gt; post that operators in lower levels bind more tightly. So to get the effect we want, we need to move the &lt;code&gt;#&lt;/code&gt; rule above the &lt;code&gt;apply&lt;/code&gt; level in the grammar.&lt;/p&gt; 
 
&lt;p&gt;First we delete the rule from its original location: &lt;code&gt;DELETE_RULE&lt;/code&gt; takes the grammar, the entry, and the symbols on the left-hand side of the rule, followed by &lt;code&gt;END&lt;/code&gt;; you don&amp;#8217;t have to say in what level it appears. Then we add the rule at a new location: we create a new level &lt;code&gt;#&lt;/code&gt; containing the rule from the original grammar, and add it before the level named &lt;code&gt;apply&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;There are several ways to specify where a level is inserted: &lt;code&gt;BEFORE&lt;/code&gt; &lt;em&gt;level&lt;/em&gt; and &lt;code&gt;AFTER&lt;/code&gt; &lt;em&gt;level&lt;/em&gt; put it before or after some other level; &lt;code&gt;LEVEL&lt;/code&gt; &lt;em&gt;level&lt;/em&gt; adds rules to an existing level (you will be warned but not stopped from changing the label or associativity of the level); &lt;code&gt;FIRST&lt;/code&gt; and &lt;code&gt;LAST&lt;/code&gt; put the level before or after all other levels. If you don&amp;#8217;t specify, rules are added to the topmost level in the entry. The resulting grammar works just as if you had given it all at once, making the insertions in the specified places. (However, it is not very clear from the code how ordering works when inserting rules into an existing level; it is perhaps best not to rely on the order of rules in a level anyway.)&lt;/p&gt; 
 
&lt;p&gt;Finally we register the extension. The &lt;code&gt;Make&lt;/code&gt; argument to &lt;code&gt;OCamlSyntaxExtension&lt;/code&gt; returns a &lt;code&gt;Sig.Camlp4Syntax&lt;/code&gt; for some reason (in &lt;code&gt;Register.ml&lt;/code&gt; it is just ignored) so we &lt;code&gt;include Syntax&lt;/code&gt; to provide it.&lt;/p&gt; 
 
&lt;p&gt;(The complete code for this example is &lt;a href='http://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/camlp4-syntax-extensions/pa_jquery'&gt;here&lt;/a&gt;.)&lt;/p&gt; 
&lt;b&gt;Transforming the AST&lt;/b&gt; 
&lt;p&gt;Let&amp;#8217;s do a slightly more complicated example involving some transformation of the parsed AST. It often comes up that we want to &lt;code&gt;let&lt;/code&gt;-bind the value of an expression to a name, trapping exceptions, then evaluate the body of the &lt;code&gt;let&lt;/code&gt; outside the scope of the exception handler. This is a bit painful to write in stock OCaml; we can only straightforwardly express trapping exceptions in the whole &lt;code&gt;let&lt;/code&gt; expression:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; 
  &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;A nice alternative is to use thunks to delay the evaluation of the body, doing it outside the scope of the &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;with&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; 
   &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt;&lt;span class='bp'&gt;()&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;(We must thunkify the exception handler to make the types work out.) This is simple enough to do by hand, but let&amp;#8217;s give it some syntactic sugar:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;e1&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='n'&gt;e2&lt;/span&gt; 
  &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;h&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;which should expand to the thunkified version above. (The idea and syntax are taken from Martin Jambon&amp;#8217;s &lt;a href='http://martin.jambon.free.fr/micmatch.html'&gt;micmatch&lt;/a&gt; extension.)&lt;/p&gt; 
 
&lt;p&gt;Let&amp;#8217;s look at the existing rules in &lt;code&gt;Camlp4OCamlRevisedParser.ml&lt;/code&gt; for &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;try&lt;/code&gt; to get an idea of how to parse the &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;try&lt;/code&gt; form:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;let&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;opt_rec&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;bi&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;binding&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;in&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;SELF&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='k'&gt;rec&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;bi&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
  &lt;span class='o'&gt;...&lt;/span&gt; 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;try&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;sequence&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;with&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;match_case&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;mksequence&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;For &lt;code&gt;let&lt;/code&gt;, the &lt;code&gt;opt_rec&lt;/code&gt; entry parses an optional &lt;code&gt;rec&lt;/code&gt; keyword (we see there is a special antiquotation for interpolating &lt;code&gt;rec&lt;/code&gt;). &lt;code&gt;Binding&lt;/code&gt; parses a group of bindings separated by &lt;code&gt;and&lt;/code&gt;. &lt;code&gt;SELF&lt;/code&gt; is just &lt;code&gt;expr&lt;/code&gt;. For &lt;code&gt;try&lt;/code&gt;, &lt;code&gt;sequence&lt;/code&gt; is a sequence of expressions separated by &lt;code&gt;;&lt;/code&gt;, and &lt;code&gt;match_case&lt;/code&gt; is a group of match cases separated by &lt;code&gt;|&lt;/code&gt;. (These entries are both a little different in the original syntax, to account for the different semicolon rules and the &lt;code&gt;[]&lt;/code&gt; delimiters around the match cases.) Recall that &lt;code&gt;Camlp4OCamlRevisedParser.ml&lt;/code&gt; uses the revised syntax quotations, so we have &lt;code&gt;[]&lt;/code&gt; around the match cases. The call to &lt;code&gt;mksequence&amp;#39;&lt;/code&gt; just wraps a &lt;code&gt;do {}&lt;/code&gt; around a sequence if necessary; more on this below.&lt;/p&gt; 
 
&lt;p&gt;The parsing rule we want is a combination of these. Here is the extension:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='nc'&gt;EXTEND&lt;/span&gt; &lt;span class='nc'&gt;Gram&lt;/span&gt; 
    &lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;LEVEL&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;top&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; 
      &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;let&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;try&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;opt_rec&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;bi&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;binding&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;in&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
        &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;sequence&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;with&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;match_case&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
            &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; 
              &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;function&lt;/span&gt; 
                 &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;match_case&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;w&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                     &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;match_case&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; 
                       &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;w&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; 
                     &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
                 &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;mc&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;mc&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
              &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;list_of_match_case&lt;/span&gt; &lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
          &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; 
            &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='k'&gt;rec&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='n'&gt;r&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;bi&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;{&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;}&lt;/span&gt; 
             &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='kt'&gt;list&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;])&lt;/span&gt;&lt;span class='bp'&gt;()&lt;/span&gt; 
          &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
      &lt;span class='o'&gt;]&lt;/span&gt; 
    &lt;span class='o'&gt;];&lt;/span&gt; 
  &lt;span class='nc'&gt;END&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We put &lt;code&gt;rec&lt;/code&gt; after &lt;code&gt;try&lt;/code&gt; (following &lt;code&gt;micmatch&lt;/code&gt;), which is a little weird &lt;s&gt;, but if we put it before we would need to look ahead to
disambiguate `let` from `let try`; once we parse `opt_rec` we are
committed to one rule or the other&lt;/s&gt; ; instead we could start the rule &lt;code&gt;&amp;quot;let&amp;quot;; r = opt_rec; &amp;quot;try&amp;quot;&lt;/code&gt;, which has no ambiguity with the ordinary &lt;code&gt;let&lt;/code&gt; rule because the &lt;code&gt;&amp;quot;let&amp;quot;; opt_rec&lt;/code&gt; prefix is factored out; the parser doesn&amp;#8217;t choose between the rules until it tries to parse &lt;code&gt;try&lt;/code&gt;. After &lt;code&gt;in&lt;/code&gt; we parse &lt;code&gt;sequence&lt;/code&gt; rather than &lt;code&gt;SELF&lt;/code&gt;; this seems like a good choice because there is a &lt;code&gt;with&lt;/code&gt; to end the sequence.&lt;/p&gt; 
 
&lt;p&gt;Now, to transform the AST, we map over the match cases. The &lt;code&gt;match_case&lt;/code&gt; entry returns a list of cases separated by &lt;code&gt;Ast.McOr&lt;/code&gt;; we call &lt;code&gt;list_of_match_case&lt;/code&gt; to get an ordinary list. For each case, we match the pattern, &lt;code&gt;when&lt;/code&gt; clause, and expression on the right-hand side (these are packaged in an &lt;code&gt;Ast.McArr&lt;/code&gt;, where the &lt;code&gt;when&lt;/code&gt; clause field is &lt;code&gt;Ast.ExNil&lt;/code&gt; if there is no &lt;code&gt;when&lt;/code&gt; clause), and return it with the expression thunkified. Then we return the whole &lt;code&gt;let&lt;/code&gt; inside &lt;code&gt;try&lt;/code&gt;, with the body sequence thunkified.&lt;/p&gt; 
 
&lt;p&gt;We have to add a &lt;code&gt;do {}&lt;/code&gt; around the body, creating an &lt;code&gt;Ast.ExSeq&lt;/code&gt; node, because that&amp;#8217;s what is expected by &lt;code&gt;Camlp4Ast2OCamlAst.ml&lt;/code&gt;&amp;#8212;recall from the &lt;a href='/2010/03/reading-camlp4-part-5-filters.html'&gt;filters&lt;/a&gt; post that the Camlp4 AST is translated to an OCaml AST and marshalled to the compiler. If we forget this (and &amp;#8220;we&amp;#8221; often forget these idiosyncrasies) then we get the error &amp;#8221;&lt;code&gt;expr; expr: not allowed here, use do {...} or [|...|] to surround them&lt;/code&gt;&amp;#8221;, which is pretty helpful as these errors go.&lt;/p&gt; 
 
&lt;p&gt;(The complete code for this example is &lt;a href='http://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/camlp4-syntax-extensions/pa_let_try'&gt;here&lt;/a&gt;.)&lt;/p&gt; 
&lt;b&gt;Extending pattern matching&lt;/b&gt; 
&lt;p&gt;As a final example, let&amp;#8217;s extend OCaml&amp;#8217;s pattern syntax. In the &lt;a href='/2010/08/reading-camlp4-part-9-implementing.html'&gt;quotations&lt;/a&gt; post we noted that JSON quotations in a pattern are not very useful, because we would usually like a pattern to match even if the fields of an object come in a different order or there are extra fields. To keep the code short let&amp;#8217;s abstract the problem a little and consider matching association lists: if we write a match case&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;alist&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;we would like it to match association lists with &lt;code&gt;&amp;quot;foo&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;bar&amp;quot;&lt;/code&gt; keys, in any order, with any extra pairs in the list. Our translation looks like this:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
               &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; 
              &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
               &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
       &lt;span class='k'&gt;with&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;true&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
               &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;),&lt;/span&gt; 
              &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
               &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;))&lt;/span&gt; 
       &lt;span class='k'&gt;with&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;y&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This might seem overcomplicated, and it is true that we could simplify it for this case. But the built-in pattern syntax is complicated, and it is tricky handling all the cases to make things work smoothly; the strategy that produces the code above will handle some (but not all) of the complications. (We&amp;#8217;ll consider some improvements below.)&lt;/p&gt; 
 
&lt;p&gt;The basic idea is that when we come to an &lt;code&gt;alist&lt;/code&gt; we replace it with a new fresh name, then do further matching in a &lt;code&gt;when&lt;/code&gt; clause, so if it fails we can continue to the next case by returning &lt;code&gt;false&lt;/code&gt;. In the &lt;code&gt;when&lt;/code&gt; clause we look up the keys, putting them in &lt;code&gt;option&lt;/code&gt;s, then match on the &lt;code&gt;option&lt;/code&gt;s; we handle nested patterns (to the right of a key) by embedding them in the &lt;code&gt;when&lt;/code&gt; clause match. The &lt;code&gt;when&lt;/code&gt; clause match also binds variables appearing in the original pattern, so they are available to the &lt;code&gt;when&lt;/code&gt; clause of the original case (if there is one). Finally, we do the whole thing over again in the match case body to provide bindings to the original body.&lt;/p&gt; 
 
&lt;p&gt;In order to implement this we&amp;#8217;ll use both a syntax extension and a filter. The reason is that we&amp;#8217;d like to extend the &lt;code&gt;patt&lt;/code&gt; entry, but to do the AST transformation we sketched above we need to transform &lt;code&gt;match_case&lt;/code&gt;s. We could replace the &lt;code&gt;match_case&lt;/code&gt; part of the parser as well but that seems needlessly hairy, and generally when writing a syntax extension we&amp;#8217;d like to touch as little of the parser as possible so it interoperates well with other extensions.&lt;/p&gt; 
 
&lt;p&gt;First, here is the syntax extension:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='nc'&gt;EXTEND&lt;/span&gt; &lt;span class='nc'&gt;Gram&lt;/span&gt; 
    &lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;LEVEL&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;simple&amp;quot;&lt;/span&gt; 
    &lt;span class='o'&gt;[[&lt;/span&gt; 
       &lt;span class='s2'&gt;&amp;quot;alist&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;[&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
         &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
           &lt;span class='nc'&gt;LIST0&lt;/span&gt; 
             &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;expr&lt;/span&gt; &lt;span class='nc'&gt;LEVEL&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;simple&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;,&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
               &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;patt&lt;/span&gt; &lt;span class='nc'&gt;LEVEL&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;simple&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                 &lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;PaOlbi&lt;/span&gt; &lt;span class='o'&gt;(_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; 
             &lt;span class='nc'&gt;SEP&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;;&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
       &lt;span class='s2'&gt;&amp;quot;]&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
         &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;uid&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;alist&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;paSem_of_list&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
    &lt;span class='o'&gt;]];&lt;/span&gt; 
  &lt;span class='nc'&gt;END&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We extend the &lt;code&gt;simple&lt;/code&gt; level of the &lt;code&gt;patt&lt;/code&gt; entry, which parses primitive patterns. Inside &lt;code&gt;alist []&lt;/code&gt; we parse a list of &lt;code&gt;expr&lt;/code&gt; / &lt;code&gt;patt&lt;/code&gt; pairs; we parse &lt;code&gt;expr&lt;/code&gt; at the &lt;code&gt;simple&lt;/code&gt; level or else it would parse the whole pair as an &lt;code&gt;expr&lt;/code&gt;, and the same for &lt;code&gt;patt&lt;/code&gt; just in case. Then we return the pair of expression and pattern in an &lt;code&gt;Ast.PaOlbi&lt;/code&gt; (ordinarily used for optional argument defaults in function definitions). Why? Well, we need to return something of type &lt;code&gt;patt&lt;/code&gt;, but we need somehow to get the &lt;code&gt;expr&lt;/code&gt; to our filter, and this is the only &lt;code&gt;patt&lt;/code&gt; constructor that holds an &lt;code&gt;expr&lt;/code&gt;. (As an alternative we could parse a &lt;code&gt;patt&lt;/code&gt; instead of an &lt;code&gt;expr&lt;/code&gt;, but then we&amp;#8217;d need to translate it to an &lt;code&gt;expr&lt;/code&gt; at the point we use it.) Finally we return the list wrapped in a data constructor so we can recognize it easily in the filter; because it is lower-case, we can be sure that &amp;#8220;alist&amp;#8221; is not the identifier of a real data constructor.&lt;/p&gt; 
 
&lt;p&gt;Now let&amp;#8217;s look at the filter. First, some helper functions:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;fresh&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='mi'&gt;0&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='n'&gt;incr&lt;/span&gt; &lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='s2'&gt;&amp;quot;__pa_alist_patt_&amp;quot;&lt;/span&gt;  &lt;span class='o'&gt;^&lt;/span&gt; &lt;span class='n'&gt;string_of_int&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;expr_tup_of_list&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;vs&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;tup&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;exCom_of_list&lt;/span&gt; &lt;span class='n'&gt;vs&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;patt_tup_of_list&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;function&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;ps&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;tup&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;paCom_of_list&lt;/span&gt; &lt;span class='n'&gt;ps&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We have a function to generate fresh names, a function to turn a list of expressions into a tuple, and a similar function for patterns. The reason we need these latter two is that a tuple with 0 or 1 elements is not allowed by &lt;code&gt;Camlp4Ast2OCamlAst.ml&lt;/code&gt; (the empty &amp;#8220;tuple&amp;#8221; is actually a special identifier in the Camlp4 AST). Next, the main rewrite function:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;rewrite&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The function takes the parts of an &lt;code&gt;Ast.McArr&lt;/code&gt; (that is, a match case). We&amp;#8217;re going to map over the pattern &lt;code&gt;p&lt;/code&gt;, building up a function &lt;code&gt;k&lt;/code&gt; as we encounter nested &lt;code&gt;alist&lt;/code&gt; forms. We want to generate the same matching code in the &lt;code&gt;when&lt;/code&gt; clause and the body, so &lt;code&gt;k&lt;/code&gt; is parameterized with an expression in case of success (the original &lt;code&gt;when&lt;/code&gt; clause or the body) and in case of failure (&lt;code&gt;false&lt;/code&gt; or &lt;code&gt;assert
false&lt;/code&gt;). We will build &lt;code&gt;k&lt;/code&gt; from the inside out, starting with a function that just returns the success expression.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;object&lt;/span&gt; 
        &lt;span class='k'&gt;inherit&lt;/span&gt; &lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;super&lt;/span&gt; 
 
        &lt;span class='k'&gt;method&lt;/span&gt; &lt;span class='n'&gt;patt&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
          &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;super&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;uid&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;alist&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;l&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;id&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;fresh&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
                &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
                  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; 
                    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;function&lt;/span&gt; 
                       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;PaOlbi&lt;/span&gt; &lt;span class='o'&gt;(_,&lt;/span&gt; &lt;span class='o'&gt;_,&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
                       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
                    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;list_of_patt&lt;/span&gt; &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='bp'&gt;[]&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
                &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;vs&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
                  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; 
                    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='o'&gt;(_,&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                       &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; 
                         &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;lid&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='o'&gt;$)&lt;/span&gt; 
                         &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
                       &lt;span class='o'&gt;&amp;gt;&amp;gt;)&lt;/span&gt; 
                    &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
                &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;ps&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
                  &lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; 
                    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='o'&gt;_)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;)&lt;/span&gt; 
                    &lt;span class='n'&gt;l&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
                &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;k&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
                &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; 
                  &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                     &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; 
                       &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;expr_tup_of_list&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='n'&gt;vs&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
                         &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;patt_tup_of_list&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='n'&gt;ps&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;k&amp;#39;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; 
                         &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; 
                     &lt;span class='o'&gt;&amp;gt;&amp;gt;);&lt;/span&gt; 
                &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;lid&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt;&lt;span class='n'&gt;id&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; 
      &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;Ast.map&lt;/code&gt; object provides methods to map each syntactic class of the AST, along with default implementations which return the node unchanged. We extend it to walk over the pattern, leaving it unchanged except when we come to our special &lt;code&gt;alist&lt;/code&gt; constructor. In that case we generate a fresh name, which we return as the value of the function. Then we extract the &lt;code&gt;expr&lt;/code&gt; / &lt;code&gt;patt&lt;/code&gt; pairs and map them to &lt;code&gt;try Some (List.assoc ...&lt;/code&gt; expressions and &lt;code&gt;Some&lt;/code&gt; patterns. Finally we extend &lt;code&gt;k&lt;/code&gt; by matching all the expressions against all the patterns; if the match succeeds we call the previous &lt;code&gt;k&lt;/code&gt;, otherwise the failure expression. Since we build &lt;code&gt;k&lt;/code&gt; from the inside out, we transform subpatterns first (by matching over &lt;code&gt;super#patt p&lt;/code&gt;).&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;patt&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='bp'&gt;true&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;expr&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;match_case&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;w&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We call &lt;code&gt;map#patt&lt;/code&gt; on &lt;code&gt;p&lt;/code&gt; to replace special &lt;code&gt;alist&lt;/code&gt; constructor nodes with fresh names and build up &lt;code&gt;k&lt;/code&gt;, then call the resulting &lt;code&gt;k&lt;/code&gt; on the &lt;code&gt;when&lt;/code&gt; clause (if there is no &lt;code&gt;when&lt;/code&gt; clause we replace it with &lt;code&gt;true&lt;/code&gt;) and body, and finally return the result as a &lt;code&gt;match_case&lt;/code&gt;, completing the rewrite function.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;object&lt;/span&gt; 
        &lt;span class='k'&gt;inherit&lt;/span&gt; &lt;span class='nn'&gt;Ast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;map&lt;/span&gt; &lt;span class='k'&gt;as&lt;/span&gt; &lt;span class='n'&gt;super&lt;/span&gt; 
 
        &lt;span class='k'&gt;method&lt;/span&gt; &lt;span class='n'&gt;match_case&lt;/span&gt; &lt;span class='n'&gt;mc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
          &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;super&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;match_case&lt;/span&gt; &lt;span class='n'&gt;mc&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;:&lt;/span&gt;&lt;span class='n'&gt;match_case&lt;/span&gt;&lt;span class='o'&gt;@_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt;&lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;w&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;$&lt;/span&gt;&lt;span class='n'&gt;e&lt;/span&gt;&lt;span class='o'&gt;$&lt;/span&gt; &lt;span class='o'&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
                &lt;span class='n'&gt;rewrite&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt;&lt;span class='n'&gt;loc&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='n'&gt;w&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
      &lt;span class='k'&gt;end&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='o'&gt;#&lt;/span&gt;&lt;span class='n'&gt;str_item&lt;/span&gt; 
 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;AstFilters&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;register_str_item_filter&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We extend &lt;code&gt;Ast.map&lt;/code&gt; again to call the rewrite function on each &lt;code&gt;match_case&lt;/code&gt;, then register the resulting filter.&lt;/p&gt; 
 
&lt;p&gt;The code above handles &lt;code&gt;when&lt;/code&gt; clauses and nested &lt;code&gt;alist&lt;/code&gt; patterns, and interacts properly with ordinary OCaml patterns. However, it completely falls down on nested pattern alternatives. If we write&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;alist&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;alist&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;fooz&amp;quot;&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;we get this mess:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_2&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;fooz&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_2&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
             &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
       &lt;span class='k'&gt;with&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
           &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;List&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;assoc&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;__&lt;/span&gt;&lt;span class='n'&gt;pa_alist_patt_1&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
                  &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Not_found&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
            &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;true&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
       &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
      &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='o'&gt;...&lt;/span&gt; &lt;span class='c'&gt;(* the same mess for the body *)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The first problem is that both arms of an alternative must bind the same names, but we have replaced them with two different fresh names. The second problem is that we have blindly treated alternative &lt;code&gt;alist&lt;/code&gt; patterns as being nested one inside the other. A solution to both these problems is to split nested alternatives into separate cases, at the cost of duplicating the &lt;code&gt;when&lt;/code&gt; clause and body in each.&lt;/p&gt; 
 
&lt;p&gt;Jeremy Yallop&amp;#8217;s &lt;a href='http://code.google.com/p/ocaml-patterns'&gt;patterns&lt;/a&gt; framework (see &lt;a href='http://github.com/jaked/patterns'&gt;here&lt;/a&gt; for an update that works with OCaml 3.12.0) allows multiple pattern extensions to coexist, and provides some common facilities to make them easier to write. In particular it splits nested alternatives into separate cases. Another deficiency in the code above is that it duplicates the match expression (built in &lt;code&gt;k&lt;/code&gt;) in the &lt;code&gt;when&lt;/code&gt; clause and body. This can be avoided by computing the body within the &lt;code&gt;when&lt;/code&gt; clause, setting a reference, and dereferencing it in the body. However, the reference must be bound outside the &lt;code&gt;match_case&lt;/code&gt; to be visible both in the &lt;code&gt;when&lt;/code&gt; clause and the body, so this approach must transform each AST node that contains &lt;code&gt;match_case&lt;/code&gt;s in order to bind the refs in the right place. The &lt;code&gt;patterns&lt;/code&gt; framework handles this as well.&lt;/p&gt; 
 
&lt;p&gt;(The complete code for this example is &lt;a href='http://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/camlp4-syntax-extensions/pa_alist_patt'&gt;here&lt;/a&gt;. A version using the &lt;code&gt;patterns&lt;/code&gt; framework is &lt;a href='http://github.com/jaked/patterns/blob/master/applications/alist/pa_alist.ml'&gt;here&lt;/a&gt;.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-2352334798898086638?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/2352334798898086638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/09/reading-camlp4-part-11-syntax.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/2352334798898086638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/2352334798898086638'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/09/reading-camlp4-part-11-syntax.html' title='Reading Camlp4, part 11: syntax extensions'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-1791120058389526317</id><published>2010-08-26T14:45:00.001-07:00</published><updated>2010-08-26T14:45:59.626-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ocamljs'/><title type='text'>ocamljs 0.3</title><content type='html'>&lt;p&gt;I am happy to announce version 0.3 of ocamljs. Ocamljs is a system for compiling OCaml to Javascript. It includes a Javascript back-end for the OCaml compiler, as well as several support libraries, such as bindings to the browser DOM. Ocamljs also works with &lt;a href='http://jaked.github.com/orpc'&gt;orpc&lt;/a&gt; for RPC over HTTP, and &lt;a href='http://jaked.github.com/froc'&gt;froc&lt;/a&gt; for functional reactive browser programming.&lt;/p&gt; 
 
&lt;p&gt;Changes since version 0.2 include:&lt;/p&gt; 
 
&lt;ul&gt; 
&lt;li&gt;support for OCaml 3.11.x and 3.12.0&lt;/li&gt; 
 
&lt;li&gt;jQuery binding (contributed by Dave Benjamin)&lt;/li&gt; 
 
&lt;li&gt;full support for OCaml objects (interoperable with Javascript objects)&lt;/li&gt; 
 
&lt;li&gt;Lwt 2.x support&lt;/li&gt; 
 
&lt;li&gt;ocamllex and ocamlyacc support&lt;/li&gt; 
 
&lt;li&gt;better interoperability with Javascript&lt;/li&gt; 
 
&lt;li&gt;many small fixes and improvements&lt;/li&gt; 
&lt;/ul&gt; 
 
&lt;p&gt;Development of ocamljs has moved from Google Code to Github; see&lt;/p&gt; 
 
&lt;ul&gt; 
&lt;li&gt;project page: &lt;a href='http://github.com/jaked/ocamljs'&gt;http://github.com/jaked/ocamljs&lt;/a&gt;&lt;/li&gt; 
 
&lt;li&gt;documentation: &lt;a href='http://jaked.github.com/ocamljs'&gt;http://jaked.github.com/ocamljs&lt;/a&gt;&lt;/li&gt; 
 
&lt;li&gt;downloads: &lt;a href='http://github.com/jaked/ocamljs/downloads'&gt;http://github.com/jaked/ocamljs/downloads&lt;/a&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;b&gt;Comparison to js_of_ocaml&lt;/b&gt; 
&lt;p&gt;Since I last did an &lt;code&gt;ocamljs&lt;/code&gt; release, a new OCaml-to-Javascript system has arrived, &lt;a href='http://ocsigen.org/js_of_ocaml/'&gt;&lt;code&gt;js_of_ocaml&lt;/code&gt;&lt;/a&gt;. I want to say a little about how the two systems compare:&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;Ocamljs&lt;/code&gt; is a back-end to the existing OCaml compiler; it translates the &amp;#8220;lambda&amp;#8221; intermediate language to Javascript. (This is also where the bytecode and native code back-ends connect to the common front-end.) &lt;code&gt;Js_of_ocaml&lt;/code&gt; post-processes ordinary OCaml bytecode (compiled and linked with the ordinary OCaml bytecode compiler) into Javascript. With &lt;code&gt;ocamljs&lt;/code&gt; you need a special installation of the compiler (and special support for &lt;code&gt;ocamlbuild&lt;/code&gt; and &lt;code&gt;ocamlfind&lt;/code&gt;), you need to recompile libraries, and you need the OCaml source to build it. With &lt;code&gt;js_of_ocaml&lt;/code&gt; you don&amp;#8217;t need any of this.&lt;/p&gt; 
 
&lt;p&gt;Since &lt;code&gt;ocamljs&lt;/code&gt; recompiles libraries, it&amp;#8217;s possible to special-case code for the Javascript build to take advantage of Javascript facilities. For example, &lt;code&gt;ocamljs&lt;/code&gt; implements the &lt;code&gt;Buffer&lt;/code&gt; module on top of Javascript arrays instead of strings, for better performance. Similarly, it implements &lt;code&gt;CamlinternalOO&lt;/code&gt; to use Javascript method dispatch directly instead of layering OCaml method dispatch on top. &lt;code&gt;Js_of_ocaml&lt;/code&gt; can&amp;#8217;t do this (or at least it would be necessary to recognize the compiled bytecode and replace it with the special case).&lt;/p&gt; 
 
&lt;p&gt;Because &lt;code&gt;js_of_ocaml&lt;/code&gt; works from bytecode, it can&amp;#8217;t always know the type of values (at the bytecode level, &lt;code&gt;int&lt;/code&gt;s, &lt;code&gt;bool&lt;/code&gt;s, and &lt;code&gt;char&lt;/code&gt;s all have the same representation, for example). This makes interoperating with native Javascript more difficult: you usually need conversion functions between the OCaml and Javascript representation of values when you call a Javascript function from OCaml. &lt;code&gt;Ocamljs&lt;/code&gt; has more information to work with, and can represent OCaml bools as Javascript bools, for example, so you can usually call a Javascript function from OCaml without conversions.&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;Ocamljs&lt;/code&gt; has a mixed representation of strings: literal strings and the result of &lt;code&gt;^&lt;/code&gt;, &lt;code&gt;Buffer.contents&lt;/code&gt;, and &lt;code&gt;Printf.sprintf&lt;/code&gt; are all immutable Javascript strings; strings created with &lt;code&gt;String.create&lt;/code&gt; are mutable strings implemented by Javascript arrays (with a &lt;code&gt;toString&lt;/code&gt; method which returns the represented string). This is good for interoperability&amp;#8212;you can usually pass a string directly to Javascript&amp;#8212;but it doesn&amp;#8217;t match regular OCaml&amp;#8217;s semantics, and it can cause runtime failures (e.g. if you try to mutate an immutable string). &lt;code&gt;Js_of_ocaml&lt;/code&gt; implements only mutable strings, so you need conversions when calling Javascript, but the semantics match regular OCaml.&lt;/p&gt; 
 
&lt;p&gt;With &lt;code&gt;ocamljs&lt;/code&gt;, Javascript objects can be called from OCaml using the ordinary OCaml method-call syntax, and objects written in OCaml can be called using the ordinary Javascript syntax. With &lt;code&gt;js_of_ocaml&lt;/code&gt;, a special syntax is needed to call Javascript objects, and OCaml objects can&amp;#8217;t easily be called from Javascript. However, there is an advantage to having a special call syntax: with &lt;code&gt;ocamljs&lt;/code&gt; it is not possible to partially apply calls to native Javascript methods, but this is not caught by the compiler, so there can be a runtime failure.&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;Ocamljs&lt;/code&gt; supports inline Javascript, while &lt;code&gt;js_of_ocaml&lt;/code&gt; does not. I think it might be possible for &lt;code&gt;js_of_ocaml&lt;/code&gt; to do so using the same approach that &lt;code&gt;ocamljs&lt;/code&gt; takes: use Camlp4 quotations to embed a syntax tree, then convert the syntax tree from its OCaml representation (as lambda code or bytecode) into Javascript. However, you would still need conversion functions between OCaml and Javascript values.&lt;/p&gt; 
 
&lt;p&gt;I haven&amp;#8217;t compared the performance of the two systems. It seems like there must be a speed penalty to translating from bytecode compared to translating from lambda code. On the other hand, while &lt;code&gt;ocamljs&lt;/code&gt; is very naive in its translation, &lt;code&gt;js_of_ocaml&lt;/code&gt; makes several optimization passes. With many programs it doesn&amp;#8217;t matter, since most of the time is spent in browser code. (For example, the &lt;code&gt;planet&lt;/code&gt; example seems to run at the same speed in &lt;a href='http://jaked.github.com/ocamljs/examples/dom/planet/'&gt;&lt;code&gt;ocamljs&lt;/code&gt;&lt;/a&gt; and &lt;a href='http://ocsigen.org/js_of_ocaml/planet/'&gt;&lt;code&gt;js_of_ocaml&lt;/code&gt;&lt;/a&gt;.) It would be interesting to compare them on something computationally intensive like Andrej Bauer&amp;#8217;s &lt;a href='http://random-art.org/'&gt;random-art.org&lt;/a&gt;.&lt;/p&gt; 
 
&lt;p&gt;&lt;code&gt;Js_of_ocaml&lt;/code&gt; is more complete and careful in its implementation of OCaml (e.g. it supports &lt;code&gt;int64&lt;/code&gt;s), and it generates much more compact code than &lt;code&gt;ocamljs&lt;/code&gt;. I hope to close the gap in these areas, possibly by borrowing some code and good ideas from &lt;code&gt;js_of_ocaml&lt;/code&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-1791120058389526317?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/1791120058389526317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/ocamljs-03.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/1791120058389526317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/1791120058389526317'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/ocamljs-03.html' title='ocamljs 0.3'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-6134067386293851263</id><published>2010-08-20T17:50:00.000-07:00</published><updated>2010-10-22T13:05:11.203-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='froc'/><category scheme='http://www.blogger.com/atom/ns#' term='lwt'/><title type='text'>Mixing monadic and direct-style code with delimited continuations</title><content type='html'>&lt;p&gt;The &lt;a href='http://ocsigen.org/lwt'&gt;Lwt&lt;/a&gt; library is a really nice way to write concurrent programs. A big downside, however, is that you can&amp;#8217;t use direct-style libraries with it. Suppose we&amp;#8217;re writing an XMPP server, and we want to parse XML as it arrives over a network connection, using Daniel Bünzli&amp;#8217;s nice &lt;a href='http://erratique.ch/software/xmlm'&gt;&lt;code&gt;xmlm&lt;/code&gt;&lt;/a&gt; library. &lt;code&gt;Xmlm&lt;/code&gt; can read from a &lt;code&gt;string&lt;/code&gt;, or from a &lt;code&gt;Pervasives.in_channel&lt;/code&gt;, or you can give it a function of type &lt;code&gt;(unit -&amp;gt; int)&lt;/code&gt; to return the next character of input. But there is no way to have it read from an Lwt thread; that is, we can&amp;#8217;t give it a function of type &lt;code&gt;(unit -&amp;gt; int Lwt.t)&lt;/code&gt;, since it doesn&amp;#8217;t know what do with an &lt;code&gt;Lwt.t&lt;/code&gt;. To keep track of the parser state at the point the input blocks, the whole library would need to be rewritten in Lwt style (i.e. monadic style).&lt;/p&gt; 
 
&lt;p&gt;Now, Lwt does provide the &lt;code&gt;Lwt_preemptive&lt;/code&gt; module, which gives you a way to spin off a preemptive thread (implemented as an ordinary OCaml thread) and wait for its result in the usual Lwt way with &lt;code&gt;bind&lt;/code&gt;. This is useful, but has two drawbacks: preemptive threads are &lt;em&gt;preemptive&lt;/em&gt;, so you&amp;#8217;re back to traditional locking if you want to operate on shared data; and preemptive threads are &lt;em&gt;threads&lt;/em&gt;, so they are much heavier than Lwt threads, and (continuing the XMPP hypothetical) it may not be feasible to use one per open connection.&lt;/p&gt; 
&lt;b&gt;Fibers&lt;/b&gt; 
&lt;p&gt;What we would really like is to be able spin off a cooperative, direct-style thread. The thread needs a way to block on Lwt threads, but when it blocks we need to be able to schedule another Lwt thread. As a cooperative thread it of course has exclusive access to the process state while it is running. A cooperative, direct-style thread is sometimes called a &lt;em&gt;coroutine&lt;/em&gt; (although to me that word connotes a particular style of inter-thread communication as well, where values are yielded between coroutines), or a &lt;em&gt;fiber&lt;/em&gt;.&lt;/p&gt; 
 
&lt;p&gt;Here&amp;#8217;s an API for mixing Lwt threads with fibers:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;await&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;start&lt;/code&gt; function spins off a fiber, returning an Lwt thread which is woken with the result of the fiber once it completes. The &lt;code&gt;await&lt;/code&gt; function (which may be called only from within a fiber) blocks on the result of an Lwt thread, allowing another Lwt thread to be scheduled while it is waiting.&lt;/p&gt; 
 
&lt;p&gt;With this API we could implement our XMPP server by calling &lt;code&gt;xmlm&lt;/code&gt; from within a fiber, and passing it a function that &lt;code&gt;await&lt;/code&gt;s the next character available on the network connection. But how do we implement it?&lt;/p&gt; 
&lt;b&gt;Delimited continuations&lt;/b&gt; 
&lt;p&gt;&lt;a href='http://okmij.org/ftp/'&gt;Oleg Kiselyov&lt;/a&gt;&amp;#8217;s recent &lt;a href='http://caml.inria.fr/pub/ml-archives/caml-list/2010/08/3567e58838e79cacc3441da7508d46fe.en.html'&gt;announcement&lt;/a&gt; of a native-code version of his &lt;code&gt;Delimcc&lt;/code&gt; library for delimited continuations in OCaml reminded me of two things:&lt;/p&gt; 
 
&lt;ol&gt; 
&lt;li&gt;I should find out what delimited continuations are.&lt;/li&gt; 
 
&lt;li&gt;They sound useful for implementing fibers.&lt;/li&gt; 
&lt;/ol&gt; 
 
&lt;p&gt;The paper describing the library, &lt;a href='http://okmij.org/ftp/continuations/caml-shift.pdf'&gt;Delimited Control in OCaml, Abstractly and Concretely&lt;/a&gt;, has a pretty good overview of delimited continuations, and section 2 of &lt;a href='http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.68.9352'&gt;A Monadic Framework for Delimited Continuations&lt;/a&gt; is helpful too.&lt;/p&gt; 
 
&lt;p&gt;The core API is small:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;prompt&lt;/span&gt; 
  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;subcont&lt;/span&gt; 
  
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;new_prompt&lt;/span&gt;   &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;prompt&lt;/span&gt; 
  
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;push_prompt&lt;/span&gt;  &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='n'&gt;prompt&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;take_subcont&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; 
    &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; &lt;span class='n'&gt;prompt&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;subcont&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;push_subcont&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt;&lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;subcont&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;I find it easiest to think about these functions as operations on the stack. A prompt is an identifier used to mark a point on the stack (the stack can be marked more than once with the same prompt). The function &lt;code&gt;new_prompt&lt;/code&gt; makes a new prompt which is not equal to any other prompt.&lt;/p&gt; 
 
&lt;p&gt;The call &lt;code&gt;push_prompt p f&lt;/code&gt; marks the stack with &lt;code&gt;p&lt;/code&gt; then runs &lt;code&gt;f&lt;/code&gt;, so the stack, growing to the right, looks like&lt;/p&gt; 
&lt;pre&gt; 
  ABCDpEFGH
&lt;/pre&gt; 
&lt;p&gt;where &lt;code&gt;ABCD&lt;/code&gt; are stack frames in the continuation of the call to &lt;code&gt;push_prompt&lt;/code&gt;, and &lt;code&gt;EFGH&lt;/code&gt; are frames created while running &lt;code&gt;f&lt;/code&gt;. If &lt;code&gt;f&lt;/code&gt; returns normally (that is, without calling &lt;code&gt;take_subcont&lt;/code&gt;) then its return value is returned by &lt;code&gt;push_prompt&lt;/code&gt;, and we are back to the original stack &lt;code&gt;ABCD&lt;/code&gt;.&lt;/p&gt; 
 
&lt;p&gt;If &lt;code&gt;take_subcont p g&lt;/code&gt; is called while running &lt;code&gt;f&lt;/code&gt;, the stack fragment &lt;code&gt;EFGH&lt;/code&gt; is packaged up as an &lt;code&gt;(&amp;#39;a,&amp;#39;b) subcont&lt;/code&gt; and passed to &lt;code&gt;g&lt;/code&gt;. You can think of an &lt;code&gt;(&amp;#39;a,&amp;#39;b) subcont&lt;/code&gt; as a function of type &lt;code&gt;&amp;#39;a -&amp;gt; &amp;#39;b&lt;/code&gt;, where &lt;code&gt;&amp;#39;a&lt;/code&gt; is the return type of the call to &lt;code&gt;take_subcont&lt;/code&gt; and &lt;code&gt;&amp;#39;b&lt;/code&gt; is the return type of the call to &lt;code&gt;push_prompt&lt;/code&gt;. &lt;code&gt;Take_subcont&lt;/code&gt; removes the fragment &lt;code&gt;pEFGH&lt;/code&gt; from the stack, and there are some new frames &lt;code&gt;IJKL&lt;/code&gt; from running &lt;code&gt;g&lt;/code&gt;, so we have&lt;/p&gt; 
&lt;pre&gt; 
  ABCDIJKL
&lt;/pre&gt; 
&lt;p&gt;Now &lt;code&gt;g&lt;/code&gt; can make use of the passed-in &lt;code&gt;subcont&lt;/code&gt; using &lt;code&gt;push_subcont&lt;/code&gt;. (Thinking of a &lt;code&gt;subcont&lt;/code&gt; as a function, &lt;code&gt;push_subcont&lt;/code&gt; is just a weird function application operator, which takes the argument as a thunk). Then the stack becomes&lt;/p&gt; 
&lt;pre&gt; 
  ABCDIJKLEFGH
&lt;/pre&gt; 
&lt;p&gt;Of course &lt;code&gt;g&lt;/code&gt; can call the &lt;code&gt;subcont&lt;/code&gt; as many times as you like.&lt;/p&gt; 
 
&lt;p&gt;A common pattern is to re-mark the stack with &lt;code&gt;push_prompt&lt;/code&gt; before calling &lt;code&gt;push_subcont&lt;/code&gt; (so &lt;code&gt;take_subcont&lt;/code&gt; may be called again). There is an optimized version of this combination called &lt;code&gt;push_delim_subcont&lt;/code&gt;, which produces the stack&lt;/p&gt; 
&lt;pre&gt; 
  ABCDIJKLpEFGH
&lt;/pre&gt; 
&lt;p&gt;The idea that a &lt;code&gt;subcont&lt;/code&gt; is a kind of function is realized by &lt;code&gt;shift0&lt;/code&gt;, which is like &lt;code&gt;take_subcont&lt;/code&gt; except that instead of passing a &lt;code&gt;subcont&lt;/code&gt; to &lt;code&gt;g&lt;/code&gt; it passes an ordinary function. The passed function just wraps a call to &lt;code&gt;push_delim_subcont&lt;/code&gt;. (It is &lt;code&gt;push_delim_subcont&lt;/code&gt; rather than &lt;code&gt;push_subcont&lt;/code&gt; for historical reasons I think&amp;#8212;see the Monadic Framework paper for a comparison of various delimited continuation primitives.)&lt;/p&gt; 
&lt;b&gt;Implementing fibers&lt;/b&gt; 
&lt;p&gt;To implement fibers, we want &lt;code&gt;start f&lt;/code&gt; to mark the stack, then run &lt;code&gt;f&lt;/code&gt;; and &lt;code&gt;await t&lt;/code&gt; to unwind the stack back to the mark, wait for &lt;code&gt;t&lt;/code&gt; to complete, then restore the stack. Here is &lt;code&gt;start&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
  
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;start&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;wait&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new_prompt&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  
    &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;push_prompt&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
        &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Return&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Fail&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Return&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;wakeup&lt;/span&gt; &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Fail&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;wakeup_exn&lt;/span&gt; &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Sleep&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; 
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='n'&gt;t&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We make a sleeping Lwt thread, and store a new prompt in a global (this is OK because we won&amp;#8217;t yield control to another Lwt thread before using it; of course this is not safe with OCaml threads). Then we mark the stack with &lt;code&gt;push_prompt&lt;/code&gt; and run the fiber. (The &lt;code&gt;let r = ... match r with ...&lt;/code&gt; is to avoid calling &lt;code&gt;Lwt.wakeup{,_exn}&lt;/code&gt; in the scope of the &lt;code&gt;try&lt;/code&gt;; we use &lt;code&gt;Lwt.state&lt;/code&gt; as a handy type to store either a result or an exception.) If the fiber completes without calling &lt;code&gt;await&lt;/code&gt; then all we do is wake up the Lwt thread with the returned value or exception.&lt;/p&gt; 
 
&lt;p&gt;Here is &lt;code&gt;await&lt;/code&gt;:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;await&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;failwith&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;await called outside start&amp;quot;&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
 
    &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;poll&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
          &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;shift0&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;ready&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
              &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
              &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
              &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;return&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
            &lt;span class='n'&gt;ignore&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;try_bind&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='n'&gt;ready&lt;/span&gt; &lt;span class='n'&gt;ready&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
          &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
          &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='nn'&gt;Lwt&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;poll&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;v&lt;/span&gt; 
            &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;assert&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;We first check to be sure that we are in the scope of &lt;code&gt;start&lt;/code&gt;, and that &lt;code&gt;t&lt;/code&gt; isn&amp;#8217;t already completed (in which case we just return its result). If we actually need to wait for &lt;code&gt;t&lt;/code&gt;, we call &lt;code&gt;shift0&lt;/code&gt;, which capture the stack fragment back to the &lt;code&gt;push_prompt&lt;/code&gt; call in &lt;code&gt;start&lt;/code&gt; (this continuation includes the subsequent &lt;code&gt;match Lwt.poll t&lt;/code&gt; and everything after the call to &lt;code&gt;await&lt;/code&gt;), then &lt;code&gt;try_bind&lt;/code&gt; so we can restore the stack fragment when &lt;code&gt;t&lt;/code&gt; completes (whether by success or failure). When &lt;code&gt;t&lt;/code&gt; completes, the &lt;code&gt;ready&lt;/code&gt; function restores the global &lt;code&gt;active_prompt&lt;/code&gt;, in case the fiber calls &lt;code&gt;await&lt;/code&gt; again, then restores the stack by calling &lt;code&gt;k&lt;/code&gt; (recall that this also re-marks the stack with &lt;code&gt;p&lt;/code&gt;, which is needed if the fiber calls &lt;code&gt;await&lt;/code&gt; again).&lt;/p&gt; 
 
&lt;p&gt;It&amp;#8217;s pretty difficult to follow what&amp;#8217;s going on here, so let&amp;#8217;s try it with stacks. After calling &lt;code&gt;start&lt;/code&gt; we have&lt;/p&gt; 
&lt;pre&gt; 
  ABCDpEFGH
&lt;/pre&gt; 
&lt;p&gt;where &lt;code&gt;ABCD&lt;/code&gt; is the continuation of &lt;code&gt;push_prompt&lt;/code&gt; in &lt;code&gt;start&lt;/code&gt; (just the return of &lt;code&gt;t&lt;/code&gt;) and &lt;code&gt;EFGH&lt;/code&gt; are frames created by the thunk passed to &lt;code&gt;start&lt;/code&gt;. Now, a call to &lt;code&gt;await&lt;/code&gt; (on an uncompleted thread) calls &lt;code&gt;shift0&lt;/code&gt;, which packs up &lt;code&gt;EFGH&lt;/code&gt; as &lt;code&gt;k&lt;/code&gt; and unwinds the stack to &lt;code&gt;p&lt;/code&gt;. The function passed to &lt;code&gt;shift0&lt;/code&gt; stores &lt;code&gt;k&lt;/code&gt; in &lt;code&gt;ready&lt;/code&gt; but doesn&amp;#8217;t call it, and control returns to &lt;code&gt;start&lt;/code&gt; (since the stack has been unwound).&lt;/p&gt; 
 
&lt;p&gt;The program continues normally until &lt;code&gt;t&lt;/code&gt; completes. Now control is in &lt;code&gt;Lwt.run_waiters&lt;/code&gt; running threads that were waiting on &lt;code&gt;t&lt;/code&gt;; one of them is our &lt;code&gt;ready&lt;/code&gt; function. When it is called, the stack is re-marked and &lt;code&gt;EFGH&lt;/code&gt; is restored, so we have&lt;/p&gt; 
&lt;pre&gt; 
  QRSTpEFGH
&lt;/pre&gt; 
&lt;p&gt;where &lt;code&gt;QRST&lt;/code&gt; is wherever we happen to be in the main program, ending in &lt;code&gt;Lwt.run_waiters&lt;/code&gt;. Now, &lt;code&gt;EFGH&lt;/code&gt; ends with the second call to &lt;code&gt;match Lwt.poll&lt;/code&gt; in &lt;code&gt;await&lt;/code&gt;, which returns the value of &lt;code&gt;t&lt;/code&gt; and continues the thunk passed to &lt;code&gt;start&lt;/code&gt;. The stack is now marked with &lt;code&gt;p&lt;/code&gt; inside &lt;code&gt;Lwt.run_waiters&lt;/code&gt;, so when &lt;code&gt;await&lt;/code&gt; is called again control returns there.&lt;/p&gt; 
&lt;b&gt;Events vs. threads&lt;/b&gt; 
&lt;p&gt;We have seen that we can use fibers to write Lwt threads in direct style. Should we abandon Lwt&amp;#8217;s monadic style entirely, and use Lwt only for its event handling?&lt;/p&gt; 
 
&lt;p&gt;First, how does each style perform? Every time a fiber blocks and resumes, we have to copy, unwind, and restore its entire stack. With Lwt threads, the &amp;#8220;stack&amp;#8221; is a bunch of linked closures in the heap, so we don&amp;#8217;t need to do anything to block or resume. On the other hand, building and garbage-collecting the closures is more expensive than pushing and popping the stack. We can imagine that which style performs better depends on the thread: if it blocks infrequently enough, the amortized cost of copying and restoring the stack might be lower than the cost of building and garbage-collecting the closures. (We can also imagine that a different implementation of delimited continuations might change this tradeoff.)&lt;/p&gt; 
 
&lt;p&gt;Second, how does the code look? The paper &lt;a href='http://www.stanford.edu/class/cs240/readings/usenix2002-fibers.pdf'&gt;Cooperative Task Management without Manual Stack Management&lt;/a&gt; considers this question in the context of the &amp;#8220;events vs. threads&amp;#8221; debate. Many of its points lose their force when translated to OCaml and Lwt&amp;#8212;closures, the &lt;code&gt;&amp;gt;&amp;gt;=&lt;/code&gt; operator, and Lwt&amp;#8217;s syntax extension go a long way toward making Lwt code look like direct style&amp;#8212;but some are still germane. In favor of fibers is that existing direct-style code need not be rewritten to work with Lwt (what motivated us in the first place). In favor of monadic style is that the type of a function reflects the possibility that it might block, yield control to another thread, and disturb state invariants.&lt;/p&gt; 
&lt;b&gt;Direct-style FRP&lt;/b&gt; 
&lt;p&gt;We could apply this idea, of replacing monadic style with direct style using delimited continuations, to other monads&amp;#8212;in particular to the &lt;a href='http://github.com/jaked/froc'&gt;&lt;code&gt;froc&lt;/code&gt;&lt;/a&gt; library for functional reactive programming. (The Scala.React FRP library also uses delimited continuations to implement direct style; see &lt;a href='http://lamp.epfl.ch/~imaier/pub/DeprecatingObserversTR2010.pdf'&gt;Deprecating the Observer Pattern&lt;/a&gt; for details.)&lt;/p&gt; 
 
&lt;p&gt;Here&amp;#8217;s the API:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;direct&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='nn'&gt;Froc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;behavior&lt;/span&gt; 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;read&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; &lt;span class='nn'&gt;Froc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;behavior&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='k'&gt;&amp;#39;&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Not surprisingly, it&amp;#8217;s just the same as for Lwt, but with a different monad and different names (I don&amp;#8217;t know if &lt;code&gt;direct&lt;/code&gt; is quite right but it is better than &lt;code&gt;start&lt;/code&gt;). There is already a function &lt;code&gt;Froc.sample&lt;/code&gt; with the same type as &lt;code&gt;read&lt;/code&gt;, but it has a different meaning: &lt;code&gt;sample&lt;/code&gt; takes a snapshot of a behavior but creates no dependency on it.&lt;/p&gt; 
 
&lt;p&gt;The implementation is very similar as well:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;ref&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; 
  
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;direct&lt;/span&gt; &lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Froc_ddg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;make_changeable&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new_prompt&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  
    &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;push_prompt&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
        &lt;span class='k'&gt;try&lt;/span&gt; &lt;span class='nn'&gt;Froc_ddg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Value&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;f&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
        &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nn'&gt;Froc_ddg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Fail&lt;/span&gt; &lt;span class='n'&gt;e&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='nn'&gt;Froc_ddg&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;write_result&lt;/span&gt; &lt;span class='n'&gt;u&lt;/span&gt; &lt;span class='n'&gt;r&lt;/span&gt; 
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Obj&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;magic&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='nn'&gt;Froc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;behavior&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;This is essentially the same code as &lt;code&gt;start&lt;/code&gt;, modulo the change of monad. However, some of the functions we need aren&amp;#8217;t exported from &lt;code&gt;Froc&lt;/code&gt;, so we need to use the underlying &lt;code&gt;Froc_ddg&lt;/code&gt; module and magic the result at the end. &lt;code&gt;Froc_ddg.make_changeable&lt;/code&gt; is the equivalent of &lt;code&gt;Lwt.wait&lt;/code&gt;: it returns an &amp;#8220;uninitialized&amp;#8221; monadic value along with a writer for that value. We use &lt;code&gt;Froc_ddg.result&lt;/code&gt; instead of &lt;code&gt;Lwt.state&lt;/code&gt; to store a value or exception, and &lt;code&gt;Froc_ddg.write_result&lt;/code&gt; instead of the pattern match and &lt;code&gt;Lwt.wakeup{,_exn}&lt;/code&gt;.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;read&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='o'&gt;!&lt;/span&gt;&lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;failwith&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;read called outside direct&amp;quot;&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
    &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;None&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
  
    &lt;span class='nn'&gt;Delimcc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;shift0&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='nn'&gt;Froc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;notify_result_b&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;begin&lt;/span&gt; &lt;span class='k'&gt;fun&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class='n'&gt;active_prompt&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nc'&gt;Some&lt;/span&gt; &lt;span class='n'&gt;p&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
        &lt;span class='n'&gt;k&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
      &lt;span class='k'&gt;end&lt;/span&gt; 
    &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
    &lt;span class='nn'&gt;Froc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sample&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;And this is essentially the same code as &lt;code&gt;await&lt;/code&gt;. A &lt;code&gt;Froc.behavior&lt;/code&gt; always has a value, so we don&amp;#8217;t poll it as we did with &lt;code&gt;Lwt.t&lt;/code&gt;, but go straight to &lt;code&gt;shift0&lt;/code&gt;. We have &lt;code&gt;Froc.try_bind&lt;/code&gt; but it&amp;#8217;s a little more compact to use use &lt;code&gt;notify_result_b&lt;/code&gt;, which passes a &lt;code&gt;result&lt;/code&gt;.&lt;/p&gt; 
&lt;b&gt;Monadic reflection&lt;/b&gt; 
&lt;p&gt;The similarity between these implementations suggests that we could use the same code to get a direct style version of any monad; we only need a way to create an uninitialized monadic value, then set it. The call to &lt;code&gt;Lwt.poll&lt;/code&gt; in &lt;code&gt;await&lt;/code&gt; is an optimization which we would have to forgo. (In both these examples we have a monad with failure, and &lt;code&gt;try_bind&lt;/code&gt;, but we could do without it.)&lt;/p&gt; 
 
&lt;p&gt;A little googling turns up Andrzej Filinski&amp;#8217;s paper &lt;a href='http://www.diku.dk/hjemmesider/ansatte/andrzej/papers/RM-abstract.html'&gt;Representing Monads&lt;/a&gt;, which reaches the same conclusion, with a lot more rigor. In that work &lt;code&gt;start&lt;/code&gt;/&lt;code&gt;direct&lt;/code&gt; are called &lt;code&gt;reify&lt;/code&gt;, and &lt;code&gt;await&lt;/code&gt;/&lt;code&gt;read&lt;/code&gt; are called &lt;code&gt;reflect&lt;/code&gt;. &lt;code&gt;Reflect&lt;/code&gt; is close to the implementations above, but in &lt;code&gt;reify&lt;/code&gt; the paper marks the stack inside a function passed to &lt;code&gt;bind&lt;/code&gt; rather than creating an uninitialized monadic value and later setting it.&lt;/p&gt; 
 
&lt;p&gt;This makes sense&amp;#8212;inside &lt;code&gt;bind&lt;/code&gt; an uninitialized monadic value is created, then set from the result of the function passed to &lt;code&gt;bind&lt;/code&gt;. So we are partially duplicating &lt;code&gt;bind&lt;/code&gt; in the code above. If we mark the stack in the right place we should be able to use &lt;code&gt;bind&lt;/code&gt; directly. It is hard to see how to make the details work out, however, since &lt;code&gt;Lwt.bind&lt;/code&gt; and &lt;code&gt;Froc.bind&lt;/code&gt; each have some cases where uninitialized values are not created.&lt;/p&gt; 
 
&lt;p&gt;(You can find the complete code for Lwt fibers &lt;a href='http://github.com/jaked/lwt-equeue/tree/master/src/lwt-fiber'&gt;here&lt;/a&gt; and direct-style &lt;code&gt;froc&lt;/code&gt; &lt;a href='http://github.com/jaked/froc/tree/master/src/froc-direct'&gt;here&lt;/a&gt;.)&lt;/p&gt; 
 
&lt;p&gt;(revised 10/22)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-6134067386293851263?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/6134067386293851263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/mixing-monadic-and-direct-style-code.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/6134067386293851263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/6134067386293851263'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/mixing-monadic-and-direct-style-code.html' title='Mixing monadic and direct-style code with delimited continuations'/><author><name>Jake Donham</name><uri>http://www.blogger.com/profile/04768087689799941690</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/_-BRxxZyoKFE/SVuunn9LDqI/AAAAAAAAALk/lSPZf6wbMwc/S220/jake-100x100.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1445545651031573301.post-2140011843858086293</id><published>2010-08-13T12:16:00.000-07:00</published><updated>2010-08-13T12:16:14.583-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='camlp4'/><title type='text'>Reading Camlp4, part 10: custom lexers</title><content type='html'>&lt;p&gt;As a final modification to our running JSON quotation example, I want to repair a problem noted in the &lt;a href='/2010/08/reading-camlp4-part-8-implementing.html'&gt;first post&lt;/a&gt;&amp;#8212;that the default lexer does not match the &lt;a href='http://www.ietf.org/rfc/rfc4627.txt'&gt;JSON spec&lt;/a&gt;&amp;#8212;and in doing so demonstrate the use of custom lexers with Camlp4 grammars. We&amp;#8217;ll parse UTF8-encoded Javascript using the &lt;a href='http://www.cduce.org/download.html#side'&gt;ulex&lt;/a&gt; library.&lt;/p&gt; 
 
&lt;p&gt;To use a custom lexer, we need to pass a module matching the &lt;code&gt;Lexer&lt;/code&gt; signature (in &lt;code&gt;camlp4/Camlp4/Sig.ml&lt;/code&gt;) to &lt;code&gt;Camlp4.PreCast.MakeGram&lt;/code&gt;. (Recall that we get back an empty grammar which we then extend with parser entries. ) Let&amp;#8217;s look at the signature and its subsignatures, and our implementation of each:&lt;/p&gt; 
&lt;b&gt;Error&lt;/b&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
    &lt;span class='k'&gt;exception&lt;/span&gt; &lt;span class='nc'&gt;E&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;print&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nn'&gt;Format&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;formatter&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;First we have a module for packaging up an exception so it can be handled generically (in particular it may be registered with &lt;code&gt;Camlp4.ErrorHandler&lt;/code&gt; for common printing and handling). We have simple exception needs so we give a simple implementation:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='k'&gt;exception&lt;/span&gt; &lt;span class='nc'&gt;E&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;print&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Format&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pp_print_string&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
  &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;M&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Camlp4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nn'&gt;ErrorHandler&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Register&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Error&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt;&lt;b&gt;Token&lt;/b&gt; 
&lt;p&gt;Next we have a module defining the tokens our lexer supports:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;Token&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; 
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; 
  
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
  
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;print&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nn'&gt;Format&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;formatter&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;match_keyword&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;bool&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;extract_string&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
  
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;...&lt;/span&gt; &lt;span class='c'&gt;(* see below *)&lt;/span&gt; 
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The type &lt;code&gt;t&lt;/code&gt; represents a token. This can be anything we like (in particular it does not need to be a variant with arms &lt;code&gt;KEYWORD&lt;/code&gt;, &lt;code&gt;EOI&lt;/code&gt;, etc. although that is the conventional representation), so long as we provide the specified functions to convert it to a string, print it to a formatter, determine if it matches a string keyword (recall that we can use literal strings in grammars; this function is called to see if the next token matches a literal string), and extract a string representation of it (called when you bind a variable to a token in a grammar&amp;#8212;e.g. &lt;code&gt;n = NUMBER&lt;/code&gt;). Here&amp;#8217;s our implementation:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;token&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;KEYWORD&lt;/span&gt;  &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;NUMBER&lt;/span&gt;   &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;STRING&lt;/span&gt;   &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;ANTIQUOT&lt;/span&gt; &lt;span class='k'&gt;of&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; 
    &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;EOI&lt;/span&gt; 
 
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Token&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;token&lt;/span&gt; 
  
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Printf&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;sprintf&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='k'&gt;match&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;KEYWORD&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;       &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;KEYWORD %S&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;NUMBER&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;        &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;NUMBER %s&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;STRING&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;        &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;STRING &lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;%s&lt;/span&gt;&lt;span class='se'&gt;\&amp;quot;&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;ANTIQUOT&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;,&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;ANTIQUOT %s: %S&amp;quot;&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;EOI&lt;/span&gt;             &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;sf&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;EOI&amp;quot;&lt;/span&gt; 
  
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;print&lt;/span&gt; &lt;span class='n'&gt;ppf&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Format&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pp_print_string&lt;/span&gt; &lt;span class='n'&gt;ppf&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
  
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;match_keyword&lt;/span&gt; &lt;span class='n'&gt;kwd&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;function&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;KEYWORD&lt;/span&gt; &lt;span class='n'&gt;kwd&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;when&lt;/span&gt; &lt;span class='n'&gt;kwd&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;kwd&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;true&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='bp'&gt;false&lt;/span&gt; 
  
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;extract_string&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='k'&gt;function&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;KEYWORD&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;NUMBER&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='nc'&gt;STRING&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;s&lt;/span&gt; 
        &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;tok&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
            &lt;span class='n'&gt;invalid_arg&lt;/span&gt; 
              &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;Cannot extract a string from this token: &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;^&lt;/span&gt; 
                 &lt;span class='n'&gt;to_string&lt;/span&gt; &lt;span class='n'&gt;tok&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Camlp4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nn'&gt;PreCast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Loc&lt;/span&gt; 
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; 
    &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='o'&gt;...&lt;/span&gt; &lt;span class='c'&gt;(* see below *)&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;Not much to it. &lt;code&gt;KEYWORD&lt;/code&gt; covers &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, and punctuation; &lt;code&gt;NUMBER&lt;/code&gt; and &lt;code&gt;STRING&lt;/code&gt; are JSON numbers and strings; as we saw &lt;a href='/2010/08/reading-camlp4-part-9-implementing.html'&gt;last time&lt;/a&gt; antiquotations are returned in &lt;code&gt;ANTIQUOT&lt;/code&gt;; finally we signal the end of the input with &lt;code&gt;EOI&lt;/code&gt;.&lt;/p&gt; 
&lt;b&gt;Filter&lt;/b&gt;&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;token_filter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;mk&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;bool&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;define_filter&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;token_filter&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;token_filter&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;token_filter&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;keyword_added&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;bool&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
    &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;keyword_removed&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;Filter&lt;/code&gt; module provides filters over token streams. We don&amp;#8217;t have a need for it in the JSON example, but it&amp;#8217;s interesting to see how it is implemented in the default lexer and used in the OCaml parser. The argument to &lt;code&gt;mk&lt;/code&gt; is a function indicating whether a string should be treated as a keyword (i.e. the literal string is used in the grammar), and the default lexer uses it to filter the token stream to convert identifiers into keywords. If we wanted the JSON parser to be extensible, we would need to take this into account; instead we&amp;#8217;ll just stub out the functions:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Filter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
  &lt;span class='k'&gt;struct&lt;/span&gt; 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;token_filter&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; 
      &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; 
 
    &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='kt'&gt;unit&lt;/span&gt; 
 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;mk&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;filter&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='n'&gt;strm&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;strm&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;define_filter&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;keyword_added&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
    &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;keyword_removed&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='bp'&gt;()&lt;/span&gt; 
  &lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt;&lt;b&gt;Lexer&lt;/b&gt; 
&lt;p&gt;Finally we have &lt;code&gt;Lexer&lt;/code&gt;, which packages up the other modules and provides the actual lexing function. The lexing function takes an initial location and a character stream, and returns a stream of token and location pairs:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='k'&gt;type&lt;/span&gt; &lt;span class='nc'&gt;Lexer&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='k'&gt;sig&lt;/span&gt; 
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; 
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Token&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Token&lt;/span&gt; &lt;span class='k'&gt;with&lt;/span&gt; &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;Loc&lt;/span&gt; 
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='nc'&gt;Error&lt;/span&gt; 
 
  &lt;span class='k'&gt;val&lt;/span&gt; &lt;span class='n'&gt;mk&lt;/span&gt; &lt;span class='o'&gt;:&lt;/span&gt; 
    &lt;span class='kt'&gt;unit&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
    &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='kt'&gt;char&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;Token&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt; &lt;span class='nn'&gt;Loc&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; &lt;span class='nn'&gt;Stream&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;span class='k'&gt;end&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;I don&amp;#8217;t want to go through the whole lexing function; it is not very interesting. But here is the main loop:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;&lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='k'&gt;rec&lt;/span&gt; &lt;span class='n'&gt;token&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;lexer&lt;/span&gt; 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;eof&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;EOI&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;newline&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;next_line&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='n'&gt;token&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lexbuf&lt;/span&gt; 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;blank&lt;/span&gt;&lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;token&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lexbuf&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='sc'&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;?&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]+&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]*&lt;/span&gt; &lt;span class='o'&gt;)?&lt;/span&gt; 
      &lt;span class='o'&gt;((&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;E&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)(&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;+&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;)?([&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;-&lt;/span&gt;&lt;span class='sc'&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class='o'&gt;]+))?&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class='nc'&gt;NUMBER&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;L&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;utf8_lexeme&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lexbuf&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;[&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;{}[]:,&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;]&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;null&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;false&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='nc'&gt;KEYWORD&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nn'&gt;L&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;utf8_lexeme&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lexbuf&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='sc'&gt;&amp;#39;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='n'&gt;set_start_loc&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;lexbuf&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='nc'&gt;STRING&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;get_stored_string&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;$&amp;quot;&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; 
      &lt;span class='n'&gt;set_start_loc&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;enc&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nn'&gt;Ulexing&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Latin1&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='k'&gt;let&lt;/span&gt; &lt;span class='n'&gt;aq&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='n'&gt;antiquot&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; &lt;span class='n'&gt;lexbuf&lt;/span&gt; &lt;span class='k'&gt;in&lt;/span&gt; 
      &lt;span class='n'&gt;c&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;enc&lt;/span&gt; &lt;span class='o'&gt;:=&lt;/span&gt; &lt;span class='nn'&gt;Ulexing&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;Utf8&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; 
      &lt;span class='n'&gt;aq&lt;/span&gt; 
 
  &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='o'&gt;_&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;illegal&lt;/span&gt; &lt;span class='n'&gt;c&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;The &lt;code&gt;lexer&lt;/code&gt; syntax is an extension provided by &lt;code&gt;ulex&lt;/code&gt;; the effect is similar to &lt;code&gt;ocamllex&lt;/code&gt;. The lexer needs to keep track of the current location and return it along with the token (&lt;code&gt;next_line&lt;/code&gt; advances the current location; &lt;code&gt;set_start_loc&lt;/code&gt; is for when a token spans multiple &lt;code&gt;ulex&lt;/code&gt; lexemes). The lexer also needs to parse antiquotations, taking into account nested quotations within them.&lt;/p&gt; 
 
&lt;p&gt;(I think it is not actually necessary to lex JSON as UTF8. The only place that non-ASCII characters can appear is in a string. To lex a string we just accumulate characters until we see a double-quote, which cannot appear as part of a multibyte character. So it would work just as well to accumulate bytes. I am no Unicode expert though. This example was extracted from the Javascript parser in &lt;a href='http://github.com/jaked/ocamljs/tree/master/src/jslib/'&gt;jslib&lt;/a&gt;, where I think UTF8 must be taken into account.)&lt;/p&gt; 
&lt;b&gt;Hooking up the lexer&lt;/b&gt; 
&lt;p&gt;There are a handful of changes we need to make to call the custom lexer:&lt;/p&gt; 
 
&lt;p&gt;In &lt;code&gt;Jq_parser&lt;/code&gt; we make the grammar with the custom lexer module, and open it so the token constructors are available; we also replace the &lt;code&gt;INT&lt;/code&gt; and &lt;code&gt;FLOAT&lt;/code&gt; cases with just &lt;code&gt;NUMBER&lt;/code&gt;; for the other cases we used the same token constructor names as the default lexer so we don&amp;#8217;t need to change anything.&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='k'&gt;open&lt;/span&gt; &lt;span class='nc'&gt;Jq_lexer&lt;/span&gt; 
 
  &lt;span class='k'&gt;module&lt;/span&gt; &lt;span class='nc'&gt;Gram&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Camlp4&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nn'&gt;PreCast&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;MakeGram&lt;/span&gt;&lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='nc'&gt;Jq_lexer&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
 
  &lt;span class='o'&gt;...&lt;/span&gt; 
      &lt;span class='o'&gt;|&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nc'&gt;NUMBER&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='nc'&gt;Jq_number&lt;/span&gt; &lt;span class='o'&gt;(&lt;/span&gt;&lt;span class='n'&gt;float_of_string&lt;/span&gt; &lt;span class='n'&gt;n&lt;/span&gt;&lt;span class='o'&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;In &lt;code&gt;Jq_quotations&lt;/code&gt; we have &lt;code&gt;Camlp4.PreCast&lt;/code&gt; open (so references to &lt;code&gt;Ast&lt;/code&gt; in the &lt;code&gt;&amp;lt;:expr&amp;lt; &amp;gt;&amp;gt;&lt;/code&gt; quotations resolve), so &lt;code&gt;EOI&lt;/code&gt; is &lt;code&gt;Camlp4.PreCast.EOI&lt;/code&gt;; we want &lt;code&gt;Jq_lexer.EOI&lt;/code&gt;, so we need to write it explicitly:&lt;/p&gt; 
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ocaml'&gt;  &lt;span class='n'&gt;json_eoi&lt;/span&gt;&lt;span class='o'&gt;:&lt;/span&gt; &lt;span class='o'&gt;[[&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='nn'&gt;Jq_parser&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;json&lt;/span&gt;&lt;span class='o'&gt;;&lt;/span&gt; &lt;span class='o'&gt;`&lt;/span&gt;&lt;span class='nn'&gt;Jq_lexer&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='nc'&gt;EOI&lt;/span&gt; &lt;span class='o'&gt;-&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;x&lt;/span&gt; &lt;span class='o'&gt;]];&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt; 
&lt;/div&gt; 
&lt;p&gt;(Recall that the backtick lets us match a constructor directly; for some reason we can&amp;#8217;t module-qualify &lt;code&gt;EOI&lt;/code&gt; without it.)&lt;/p&gt; 
 
&lt;p&gt;That&amp;#8217;s it.&lt;/p&gt; 
 
&lt;p&gt;I want to finish off this series next time by covering grammar extension, with an example OCaml syntax extension.&lt;/p&gt; 
 
&lt;p&gt;(You can find the complete code for this example &lt;a href='http://github.com/jaked/ambassadortothecomputers.blogspot.com/tree/master/_code/camlp4-custom-lexers'&gt;here&lt;/a&gt;.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1445545651031573301-2140011843858086293?l=ambassadortothecomputers.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://ambassadortothecomputers.blogspot.com/feeds/2140011843858086293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/reading-camlp4-part-10-custom-lexers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/2140011843858086293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1445545651031573301/posts/default/2140011843858086293'/><link rel='alternate' type='text/html' href='http://ambassadortothecomputers.blogspot.com/2010/08/reading-camlp4-part-10-custom-lexers.html' title='Reading Camlp4, part 10: custom lexers'/><
