<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dw="https://www.dreamwidth.org">
  <id>tag:dreamwidth.org,2010-05-25:518115</id>
  <title>Renaissance Grrrl</title>
  <subtitle>wren romano</subtitle>
  <author>
    <name>wren romano</name>
  </author>
  <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/"/>
  <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom"/>
  <updated>2016-04-27T22:08:05Z</updated>
  <dw:journal username="winterkoninkje" type="personal"/>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:108348</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/108348.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=108348"/>
    <title>Hacking projects over the next few months</title>
    <published>2016-04-27T22:08:05Z</published>
    <updated>2016-04-27T22:08:05Z</updated>
    <category term="haskell"/>
    <category term="coding"/>
    <category term="haskell planet"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;Life’s been really hectic lately, but I’ve been getting (slowly) back into working on my Haskell packages. In particular, since the switch from darcs to github I’ve started getting more comments and feature requests, which is nice. Over the next half-year or so, here’s what I’ll be up to in my free time between work on the dissertation and work on &lt;a href="https://github.com/hakaru-dev/hakaru"&gt;Hakaru&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/haskell/containers"&gt;&lt;b&gt;&lt;i&gt;containers&lt;/i&gt;&lt;/b&gt;&lt;/a&gt; — I’ve been appointed one of the new co-maintainers of our favorite venerable library. I prolly won’t be doing any major work until autumn (as mentioned when I was appointed), but I’ve had a number of conversations with David Feuer about where to take things in terms of cleaning up some old maintenance cruft.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wrengr/bytestring-trie"&gt;&lt;b&gt;&lt;i&gt;bytestring-trie&lt;/i&gt;&lt;/b&gt;&lt;/a&gt; — A few years back I started reimplementing my tries to use Bagwell’s Array Mapped Tries in lieu of Okasaki’s Big-Endian Patricia Tries, but then got stalled because life. I’ve started up on it again, and it’s just about ready to be released after a few more tweaks. Also, now that I’m working on it again I can finally clear out the backlog of API requests (sorry folks!).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wrengr/exact-combinatorics"&gt;&lt;b&gt;&lt;i&gt;exact-combinatorics&lt;/i&gt;&lt;/b&gt;&lt;/a&gt; — A user recently pointed me towards a new fast implementation of factorial making waves lately. It’s not clear just yet whether it’ll be faster than the current implementation, but should be easy enough to get going and run some benchmarks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wrengr/unification-fd"&gt;&lt;b&gt;&lt;i&gt;unification-fd&lt;/i&gt;&lt;/b&gt;&lt;/a&gt; — This one isn’t hacking so much as dissemination. I have a backlog of queries about why things are the way they are, which I need to address; and I’ve been meaning to continue the &lt;a href="http://winterkoninkje.dreamwidth.org/100478.html"&gt;tutorial&lt;/a&gt; about how to use this library for your unification needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wrengr/logfloat"&gt;&lt;b&gt;&lt;i&gt;logfloat&lt;/i&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/a&gt; — We’ve been using this a lot in Hakaru, and there are a few performance tweaks I think I can add. The main optimization area is trying to minimize the conditionals for detecting edge cases. The biggest issue has just been coming up with some decent benchmarks. The problem, of course, is that most programs making use of logfloats do a lot of other work too so it can be tricky to detect the actual effect of changes. I think this is something Hakaru can help a lot with since it makes it easy to construct all sorts of new models.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=108348" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:103978</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/103978.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=103978"/>
    <title>Abstract Binding Trees in Hakaru</title>
    <published>2015-09-21T00:40:51Z</published>
    <updated>2016-03-01T08:54:56Z</updated>
    <category term="hakaru"/>
    <category term="haskell planet"/>
    <category term="dependent types"/>
    <category term="computer science"/>
    <category term="coding"/>
    <category term="haskell"/>
    <category term="design"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;&lt;i&gt;Edit 2015.10.29: Be sure to also read &lt;a href="http://winterkoninkje.dreamwidth.org/104698.html"&gt;the followup post&lt;/a&gt; on the benefits and limitations of this approach compared to the usual untyped ABTs.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Earlier this year Neel Krishnaswami talked about abstract binding trees (ABTs) &lt;a href="http://semantic-domain.blogspot.co.uk/2015/03/abstract-binding-trees.html"&gt;[part 1]&lt;/a&gt; &lt;a href="http://semantic-domain.blogspot.co.uk/2015/03/abstract-binding-trees-addendum.html"&gt;[part 2]&lt;/a&gt;. IMO, the best way to think about ABTs is as a generalization of abstract syntax trees (ASTs), though this is not a perspective sanctioned by the CMUers I’ve talked to. CMUers oppose this way of phrasing things, in part, because the ABT libraries they’re familiar with make crucial use of the design pattern of &lt;a href="http://web.cecs.pdx.edu/~sheard/papers/JfpPearl.ps"&gt;two-level types&lt;/a&gt;; but I think the essential insights of ABTs and two-level types are quite different, and we ought to keep the benefits of these two techniques distinct.&lt;/p&gt;&lt;p&gt;Over the past year I’ve been working on the inferential language&lt;sup&gt;&lt;a href="#103978:fn1" name="103978:fnref1"&gt;1&lt;/a&gt;&lt;/sup&gt; &lt;a href="https://github.com/hakaru-dev/hakaru"&gt;Hakaru&lt;/a&gt;, and in the new version of the compiler we’re using ABTs for our syntax trees. However, contrary to Neel’s stance against using strongly-typed internal representations for syntax, we extend the ABT approach to make use of GADTs to guarantee local well-typedness— since this in turn can be used to guarantee that program transformations are also well-typed. (If you don’t want those guarantees, then take a look at Jon Sterling’s &lt;a href="http://hackage.haskell.org/package/abt"&gt;abt&lt;/a&gt; library on Hackage&lt;sup&gt;&lt;a href="#103978:fn2" name="103978:fnref2"&gt;2&lt;/a&gt;&lt;/sup&gt;.) In this post I’m going to present a simplified version of our architecture, and then talk about some of the extra stuff bringing it closer to our production architecture.&lt;/p&gt;&lt;h3&gt;First things first&lt;/h3&gt;&lt;p&gt;Since we want everything to be well-typed, we first must introduce some universe, &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;, of all the types in our language. (In Haskell we can implement such a universe by using the &lt;code&gt;-XDataKinds&lt;/code&gt; extension, so I’ll equivocate between calling &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt; a “universe” vs a “kind”.) For the rest of this post it doesn’t actually matter what lives in that universe&lt;sup&gt;&lt;a href="#103978:fn3" name="103978:fnref3"&gt;3&lt;/a&gt;&lt;/sup&gt;, just so long as things match up when they need to. Since the choice of universe is irrelevant, we could abstract over &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt; by turning on the &lt;code&gt;-XPolyKinds&lt;/code&gt; extension; but I avoid doing so below, just to help keep things more concrete.&lt;/p&gt;&lt;h3&gt;Implementing ASTs&lt;/h3&gt;&lt;p&gt;The simplest way of thinking about well-typed ASTs is that they capture the set of terms generated by a (typed) signature; that is, the fixed point of some &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;&lt;/code&gt;. Unpacking the type for &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt;&lt;/code&gt;, we have that every syntactic constructor &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;s&lt;/span&gt; ∈ &lt;span class="dt"&gt;Σ&lt;/span&gt;&lt;/code&gt; is associated with some arity (the length of the list), each argument to &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;s&lt;/span&gt;&lt;/code&gt; has some type in &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt; (the elements of the list), and applying &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;s&lt;/span&gt;&lt;/code&gt; to the right number of ASTs of the right types will generate a new AST with some type in &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt; (the second argument to &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;To implement this fixed point we define an &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;AST&lt;/span&gt;&lt;/code&gt; type which is parameterized by its signature. To ensure well-aritiedness (and well-typedness) of our ASTs with respect to that signature, we’ll need to introduce a helper type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;SArgs&lt;/span&gt;&lt;/code&gt;&lt;sup&gt;&lt;a href="#103978:fn4" name="103978:fnref4"&gt;4&lt;/a&gt;&lt;/sup&gt;. And to ensure that we obtain the &lt;em&gt;least&lt;/em&gt; fixed-point of the signature, we’ll make everything strict.&lt;/p&gt;&lt;div class="sourceCode"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;infix&lt;/span&gt;  &lt;span class="dv"&gt;4&lt;/span&gt; &lt;span class="dc"&gt;:$&lt;/span&gt;
&lt;span class="kw"&gt;infixr&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt; &lt;span class="dc"&gt;:*&lt;/span&gt;

&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    &lt;span class="dc"&gt;End&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;ast&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt;

    (&lt;span class="dc"&gt;:*&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="bv"&gt;ast&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;ast&lt;/span&gt; &lt;span class="bv"&gt;us&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;ast&lt;/span&gt; (&lt;span class="bv"&gt;u&lt;/span&gt; &lt;span class="dc"&gt;:&lt;/span&gt; &lt;span class="bv"&gt;us&lt;/span&gt;)

&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;AST&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    (&lt;span class="dc"&gt;:$&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;us&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;SArgs&lt;/span&gt; (&lt;span class="dt"&gt;AST&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt;) &lt;span class="bv"&gt;us&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;AST&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Implementing ABTs&lt;/h3&gt;&lt;p&gt;The problem with ASTs is that they have no notion of variables, and thus have no notion of variable binding. Naively we could implement binders like lambda-abstraction by having something like &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;λ&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="dc"&gt;[&lt;/span&gt;&lt;span class="bv"&gt;u&lt;/span&gt;&lt;span class="dc"&gt;,&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;&lt;span class="dc"&gt;]&lt;/span&gt; (&lt;span class="bv"&gt;u&lt;/span&gt; &lt;span class="dc"&gt;:→&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)&lt;/code&gt; but then we’d need to do a post-hoc check to ensure that the first argument to &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;λ&lt;/span&gt;&lt;/code&gt; is in fact a variable. To build that check into the datatype itself we’d have to move &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;λ&lt;/span&gt;&lt;/code&gt; into the definition of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;AST&lt;/span&gt;&lt;/code&gt; (since the first argument is of type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; rather than &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;AST&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt;). If lambda-abstraction were the only binder we had, that might not be so bad; but any real-world language has a plethora of binders, and this approach doesn’t scale.&lt;/p&gt;&lt;p&gt;The essential idea behind ABTs is to abstract over the notion of binding itself. Given a single uniform definition of what it means to be a binding form, we don’t have to worry about adding a bunch of ad-hoc constructors to our AST datatype. Moreover, we can then provide single uniform definitions for things which mess with variables and are homomorphic over the signature. Things like &lt;a href="http://semantic-domain.blogspot.co.uk/2015/03/abstract-binding-trees.html"&gt;capture-avoiding substitution&lt;/a&gt; and providing a &lt;a href="http://comonad.com/reader/2014/fast-circular-substitution/"&gt;HOAS API for our first-order representation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The crucial step is to adjust our notion of what a signature contains. The basic signatures used above only contained applicative forms; i.e., things we can apply to locally-closed terms; i.e., what are called “functors” in the logic programming community. For ABTs we’ll want to allow our signatures to include any &lt;a href="http://plato.stanford.edu/entries/generalized-quantifiers/"&gt;generalized quantifier&lt;/a&gt;. That is, our signatures will now be of type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;&lt;/code&gt;. Previously, the arguments were indexed by &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;; now, they’re indexed by &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;. The length of the list gives the number of variables being bound, the types in the list give the types of those variables, and the second component of the pair gives the type of the whole locally-open expression.&lt;/p&gt;&lt;p&gt;To implement this we need to extend our syntax tree to include variable bindings and variable uses:&lt;/p&gt;&lt;div class="sourceCode"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    &lt;span class="dc"&gt;End&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt;

    (&lt;span class="dc"&gt;:*&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;vus&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; (&lt;span class="dc"&gt;(&lt;/span&gt;&lt;span class="bv"&gt;vs&lt;/span&gt;&lt;span class="dc"&gt;,&lt;/span&gt;&lt;span class="bv"&gt;u&lt;/span&gt;&lt;span class="dc"&gt;)&lt;/span&gt; &lt;span class="dc"&gt;:&lt;/span&gt; &lt;span class="bv"&gt;vus&lt;/span&gt;)

&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    (&lt;span class="dc"&gt;:$&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vus&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;SArgs&lt;/span&gt; (&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt;) &lt;span class="bv"&gt;vus&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;

    &lt;span class="dc"&gt;Var&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;

    &lt;span class="dc"&gt;Bind&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; (&lt;span class="bv"&gt;v&lt;/span&gt; &lt;span class="dc"&gt;:&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt;) &lt;span class="bv"&gt;u&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Time for an example of how this all fits together. To add lambda-abstraction to our language we’d have &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;λ&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="dc"&gt;[&lt;/span&gt;&lt;span class="dc"&gt;(&lt;/span&gt;&lt;span class="dc"&gt;[&lt;/span&gt;&lt;span class="bv"&gt;u&lt;/span&gt;&lt;span class="dc"&gt;]&lt;/span&gt;&lt;span class="dc"&gt;,&lt;/span&gt;&lt;span class="bv"&gt;v&lt;/span&gt;&lt;span class="dc"&gt;)&lt;/span&gt;&lt;span class="dc"&gt;]&lt;/span&gt; (&lt;span class="bv"&gt;u&lt;/span&gt; &lt;span class="dc"&gt;:→&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)&lt;/code&gt;: that is, the &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;λ&lt;/span&gt;&lt;/code&gt; constructor takes a single argument which is a locally-open term, binding a single variable of type &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt;, and whose body has type &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;v&lt;/span&gt;&lt;/code&gt;. So given some &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;x&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; and &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;e&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="fv"&gt;v&lt;/span&gt;&lt;/code&gt; we’d have the AST &lt;code class="sourceCode haskell"&gt;(&lt;span class="dc"&gt;λ&lt;/span&gt; &lt;span class="dc"&gt;:$&lt;/span&gt; &lt;span class="dc"&gt;Bind&lt;/span&gt; &lt;span class="fv"&gt;x&lt;/span&gt; &lt;span class="fv"&gt;e&lt;/span&gt; &lt;span class="dc"&gt;:*&lt;/span&gt; &lt;span class="dc"&gt;End&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; (&lt;span class="fv"&gt;u&lt;/span&gt; &lt;span class="dc"&gt;:→&lt;/span&gt; &lt;span class="fv"&gt;v&lt;/span&gt;)&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;“Local” vs “global” well-typedness&lt;/h3&gt;&lt;p&gt;With the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; definition above, every term of type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="dt"&gt;Σ&lt;/span&gt; &lt;span class="fv"&gt;vs&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; must be locally well-typed according to the signature &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt;&lt;/code&gt;. I keep saying “locally” well-typed because we only actually keep track of local binding information. This is an intentional design decision. But only tracking local well-typedness does have some downsides.&lt;/p&gt;&lt;p&gt;So what are the downsides? Where could things go wrong? Given a locally-closed term (i.e., either &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Var&lt;/span&gt; &lt;span class="fv"&gt;x&lt;/span&gt;&lt;/code&gt; or &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;f&lt;/span&gt; &lt;span class="dc"&gt;:$&lt;/span&gt; &lt;span class="fv"&gt;e&lt;/span&gt;&lt;/code&gt;) any free variables that occur inside will not have their &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;-types tracked by Haskell’s type system. This introduces some room for the compiler writer to break the connection between the types of a variable’s binder and its use. That is, under the hood, every variable is represented by some unique identifier like an integer or a string. Integers and strings aren’t &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;-indexed Haskell types, thus it’s possible to construct a &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; and a &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;v&lt;/span&gt;&lt;/code&gt; with the same unique identifier, even though &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; and &lt;code class="sourceCode haskell"&gt;&lt;span class="fv"&gt;v&lt;/span&gt;&lt;/code&gt; differ. We could then &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Bind&lt;/span&gt;&lt;/code&gt; the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;u&lt;/span&gt;&lt;/code&gt; but &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Var&lt;/span&gt;&lt;/code&gt; the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="fv"&gt;v&lt;/span&gt;&lt;/code&gt;. In order to ensure global well-typedness we need to ensure this can’t happen.&lt;/p&gt;&lt;p&gt;One way is to keep track of global binding information, as we do in the paper presentation of languages. Unfortunately, to do this we’d need to teach Haskell’s typechecker about the structural rules of our language. Without a type-level implementation of sets/maps which respects all the axioms that sets/maps should, we’d be forced to do things like traverse our ASTs and rebuild them identically, but at different type indices. This is simply too hairy to stomach. Implementing the axioms ourselves is doubly so.&lt;/p&gt;&lt;p&gt;Or we could fake it, using &lt;code class="sourceCode haskell"&gt;&lt;span class="fn"&gt;unsafeCoerce&lt;/span&gt;&lt;/code&gt; to avoid the extraneous traversals or the complicated pattern matching on axioms. But doing this we’d erase all guarantees that adding global binding information has to offer.&lt;/p&gt;&lt;p&gt;A third approach, and the one we take in Hakaru, is compartmentalize the places where variables can be constructed. The variable generation code must be part of our trusted code base, but unlike the &lt;code class="sourceCode haskell"&gt;&lt;span class="fn"&gt;unsafeCoerce&lt;/span&gt;&lt;/code&gt; approach we can keep all the TCB code together in one spot rather than spread out across the whole compiler.&lt;/p&gt;&lt;h3&gt;Stratifying our data types&lt;/h3&gt;&lt;p&gt;The above definition of ABTs is a simplified version of what we actually use in Hakaru. For example, Hakaru has user-defined algebraic data types, so we also need case analysis on those data types. Alas, generic case analysis is not a generalized quantifier, thus we cannot implement it with &lt;code class="sourceCode haskell"&gt;(&lt;span class="dc"&gt;:$&lt;/span&gt;)&lt;/code&gt;. We could consider just adding case analysis to the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; definition, but then we’d start running into extensibility issues again. Instead, we can break the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; type apart into two types: one for capturing variable uses and bindings, and the other for whatever syntax we can come up with. Thus,&lt;/p&gt;&lt;div class="sourceCode"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Syntax&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    (&lt;span class="dc"&gt;:$&lt;/span&gt;) &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vus&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;SArgs&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;vus&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;Syntax&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;

&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    &lt;span class="dc"&gt;Syn&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Syntax&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; (&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt;) &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;

    &lt;span class="dc"&gt;Var&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;

    &lt;span class="dc"&gt;Bind&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; (&lt;span class="bv"&gt;v&lt;/span&gt; &lt;span class="dc"&gt;:&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt;) &lt;span class="bv"&gt;u&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, since we’re going to be extending &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Syntax&lt;/span&gt;&lt;/code&gt; with all our language-specific details, there’s not a whole lot of benefit to parameterizing over &lt;code class="sourceCode haskell"&gt;&lt;span class="bv"&gt;σ&lt;/span&gt;&lt;/code&gt;. Thus, we can simplify the types considerably by just picking some concrete &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Σ&lt;/span&gt;&lt;/code&gt; to plug in for &lt;code class="sourceCode haskell"&gt;&lt;span class="bv"&gt;σ&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;By breaking &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Syntax&lt;/span&gt;&lt;/code&gt; apart from &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; we can now extend our notion of syntax without worrying about the details of variable binding (which can be defined once and for all on &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt;). But we could still run into extensibility issues. In particular, often we want to separate the fixed-point portion of recursive types from their generating functor so that we can do things like add annotations at every node in the recursive data type. A prime example of such annotations is keeping track of free variables, as in Neel’s original post. To allow this form of extensibility we need to break up the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; type into two parts: the recursion, and the &lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Syn&lt;/span&gt;&lt;/code&gt;/&lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Var&lt;/span&gt;&lt;/code&gt;/&lt;code class="sourceCode haskell"&gt;&lt;span class="dc"&gt;Bind&lt;/span&gt;&lt;/code&gt; view of the ABT.&lt;/p&gt;&lt;div class="sourceCode"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    &lt;span class="dc"&gt;Unview&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; (&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt;) &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;

&lt;span class="fn"&gt;view&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; (&lt;span class="dt"&gt;ABT&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt;) &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;
&lt;span class="fn"&gt;view&lt;/span&gt; (&lt;span class="dc"&gt;Unview&lt;/span&gt; &lt;span class="bv"&gt;e&lt;/span&gt;) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="bv"&gt;e&lt;/span&gt;

&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; (&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt;) &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt; &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="pt"&gt;⭑&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;
    &lt;span class="dc"&gt;Syn&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Syntax&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;

    &lt;span class="dc"&gt;Var&lt;/span&gt;  &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="dc"&gt;[]&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;

    &lt;span class="dc"&gt;Bind&lt;/span&gt; &lt;span class="ot"&gt;∷&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Variable&lt;/span&gt; &lt;span class="bv"&gt;v&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="ot"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt; &lt;span class="bv"&gt;u&lt;/span&gt;)
         &lt;span class="pt"&gt;→&lt;/span&gt; &lt;span class="dt"&gt;View&lt;/span&gt; &lt;span class="bv"&gt;σ&lt;/span&gt; &lt;span class="bv"&gt;abt&lt;/span&gt; (&lt;span class="bv"&gt;v&lt;/span&gt; &lt;span class="dc"&gt;:&lt;/span&gt; &lt;span class="bv"&gt;vs&lt;/span&gt;) &lt;span class="bv"&gt;u&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, to allow arbitrary annotations we’ll replace the data type &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; with an equivalent type class. Each instance of the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; class defines some sort of annotations, and we can use the &lt;code class="sourceCode haskell"&gt;&lt;span class="fn"&gt;view&lt;/span&gt;&lt;/code&gt; and &lt;code class="sourceCode haskell"&gt;&lt;span class="fn"&gt;unview&lt;/span&gt;&lt;/code&gt; methods to move between the instance and the concrete &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;View&lt;/span&gt;&lt;/code&gt; type.&lt;/p&gt;&lt;p&gt;There’s one last form of extensibility we may want to add. Using fixed point combinators gives us a way of describing complete trees. A different way of introducing recursion is with free monads. The free-monad combinator is just like the fixed-point combinator, except that we have an additional type parameter for metavariables and we have a data constructor for using those metavariables instead of requiring the recursion to ground out with a complete syntax tree. The reasons why this might be nice to do are beyond the scope of this post, but the point is we might want to do that so we need to split the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ABT&lt;/span&gt;&lt;/code&gt; class into two parts: one for the recursion itself, and another for the annotations.&lt;/p&gt;&lt;p&gt;In the end, we have a four-level type: the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Syntax&lt;/span&gt;&lt;/code&gt;, the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;View&lt;/span&gt;&lt;/code&gt;, the annotations, and the recursion.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;a name="103978:fn1"&gt;[1]&lt;/a&gt; In the accepted/current parlance, Hakaru is a “probabilistic programming language”; but I and a number of other folks working on such languages have become disaffected with that term of late, since it’s not entirely clear what should and should not count as a “probabilistic” PL. Over the course of a number of discussions on the topic, I’ve settled on “inferential” PL as describing what is (or, at least what &lt;em&gt;I&lt;/em&gt; find) interesting about “probabilistic” PL. I’ve been meaning to write a post about the subject, and hopefully this footnote will remind me to do so.&lt;a href="#103978:fnref1"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name="103978:fn2"&gt;[2]&lt;/a&gt; N.B., the indexing used in that package is what we get if we erase/compactify the universe &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt;. That is: the erasure of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;/code&gt; is a singleton set; the erasure of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt;&lt;/code&gt; is isomorphic to the Peano numbers; the erasure of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;[&lt;/span&gt;&lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt; &lt;span class="dt"&gt;×&lt;/span&gt; &lt;span class="dt"&gt;U&lt;/span&gt;&lt;span class="dt"&gt;]&lt;/span&gt;&lt;/code&gt; is isomorphic to a list of Peano numbers; etc.&lt;a href="#103978:fnref2"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name="103978:fn3"&gt;[3]&lt;/a&gt; Though at one point I assume we have functions, &lt;code class="sourceCode haskell"&gt;(&lt;span class="dc"&gt;:→&lt;/span&gt;)&lt;/code&gt;, just for the sake of an example.&lt;a href="#103978:fnref3"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name="103978:fn4"&gt;[4]&lt;/a&gt; Ideally we’d be able to flatten this type to avoid all the overhead of the linked list implementation. In fact, the entire AST node of &lt;code class="sourceCode haskell"&gt;(&lt;span class="dc"&gt;:$&lt;/span&gt;)&lt;/code&gt; together with its &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;SArgs&lt;/span&gt;&lt;/code&gt; should be flattened. These nodes have the same general layout as the heap objects in the STG machine: a record with a pointer to the data constructor (i.e., element of the signature) followed by an appropriate number of arguments; and so in principle we ought to be able to implement them directly with a single STG heap object.&lt;a href="#103978:fnref4"&gt;↩&lt;/a&gt;&lt;/p&gt;

&lt;div class="btn-group"&gt;
&lt;a href="https://twitter.com/share?via=wrengr&amp;amp;url=http%3A%2F%2Fwinterkoninkje.dreamwidth.org%2F103978.html&amp;amp;text=Abstract%20Binding%20Trees%20in%20Hakaru" class="btn" title="Share on Twitter" target="_blank"&gt;Twitter&lt;/a&gt;
&lt;a href="https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fwinterkoninkje.dreamwidth.org%2F103978.html&amp;amp;t=Abstract%20Binding%20Trees%20in%20Hakaru" class="btn" title="Share on Facebook" target="_blank"&gt;Facebook&lt;/a&gt;
&lt;a href="https://plus.google.com/share?url=http%3A%2F%2Fwinterkoninkje.dreamwidth.org%2F103978.html" class="btn" title="Share on Google+" target="_blank"&gt;Google+&lt;/a&gt;
&lt;a href="http://www.tumblr.com/share/link?url=http%3A%2F%2Fwinterkoninkje.dreamwidth.org%2F103978.html&amp;amp;name=Abstract%20Binding%20Trees%20in%20Hakaru" class="btn" title="Share on Tumblr" target="_blank"&gt;Tumblr&lt;/a&gt;
&lt;a href="http://wordpress.com/press-this.php?u=http%3A%2F%2Fwinterkoninkje.dreamwidth.org%2F103978.html&amp;amp;t=Abstract%20Binding%20Trees%20in%20Hakaru&amp;amp;s=" class="btn" title="Share on WordPress" target="_blank"&gt;WordPress&lt;/a&gt;
&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=103978" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:92722</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/92722.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=92722"/>
    <title>Women in FP</title>
    <published>2014-05-04T22:56:51Z</published>
    <updated>2014-05-04T22:56:51Z</updated>
    <category term="feminism"/>
    <category term="haskell planet"/>
    <category term="coding"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;Katie Miller is giving a talk about FP outreach and diversity at next month's &lt;a href="http://www.erlang-factory.com/conference/show/conference-23/home/"&gt;Erlang User Conference&lt;/a&gt;. She sent a questionnaire to the &lt;a href="http://www.lambdaladies.com/"&gt;Lambda Ladies&lt;/a&gt; mailing list about our experiences, and I thought I'd share my responses here.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;What led you to pursue functional programming?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Curiosity. I was in grad school, working towards a masters in computer science. And I was particularly interested in programming languages, though I was only familiar with imperative and OO languages at that point. I saw a course on functional programming, so I signed up. Best CS decision I ever made.&lt;/p&gt;


&lt;p&gt;&lt;i&gt;What sort of perception did you have of functional programming before you learnt more about it? Was this a barrier? If so, how did you overcome this?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;All I knew at the time was that it was some sort of paradigm completely different from imperative and OO. That's it really. This was before FP started becoming popular; so, long before Clojure or Scala were invented, and long before C++ considered adding lambdas/closures to the language. Even within the FP community, Haskell was still considered the new kid on the block (despite having been around for quite some time).&lt;/p&gt;


&lt;p&gt;&lt;i&gt;What were the challenges for becoming part of the FP community?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;The main challenge was just in figuring out where the community was and how to take part. As I said, this was long before FP became popular. My first FP language was Haskell, but I'd learned it in that course on functional programming so I didn't really know what the community was like. It was a year or two after taking the class that I decided to start really using Haskell for projects. At the time I was taking part in the Perl community, so I thought I'd go searching for some Haskell mailing lists to join. That's when I found the firehose that is Haskell Cafe.&lt;/p&gt;


&lt;p&gt;&lt;i&gt;Why do you think women are underrepresented in FP, more so than in programming generally?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;I think there are a number of reasons. One of the big ones is how academic the community is. I don't mean that in the way people usually do. I'm an academic, and I love it here! No, the problem is that this creates a huge selection bias. I only really found FP by stumbling into it, and I only stumbled into it because I had a number of supportive advisors who helped foster my interest in programming languages. By the point I found FP, many women would have already been filtered out. Just getting into and affording college is a huge thing, especially for women of color. Let alone making it through undergrad and then getting into a masters program in CS without a bachelor's in CS. Let alone ending up at a school that can offer good FP classes, and finding those supportive advisors to help you along and guide you in the right direction.&lt;/p&gt;

&lt;p&gt;If my story is anything to go by, it takes a lot of privilege (and luck) just to get to the point where you discover FP. After that, then you add on all the issues about maintaining community involvement. Because the community is so academic, this heightens issues of impostor syndrome. (Even men are driven out of FP due to impostor syndrome!) And since FP tends to be sold in a hyper-intellectualized manner, this evokes the "math is hard" brand of anti-intellectualism. While this drives a lot of people away, I think it has a differentially powerful impact on women due to the way we gender the sciences. That is, FP propaganda has a habit of taking the things which cause women to be underrepresented in STEM generally, and then cranking them up to eleven.&lt;/p&gt;

&lt;p&gt;Another issue, and one I haven't seen discussed very often, is the fact that many FP communities are also FOSS communities. Women are more underrepresented in FOSS than in other CS communities, so the fact that FP tends to be FOSS means that women will tend to be more underrepresented in FP than other CS communities.&lt;/p&gt;


&lt;p&gt;&lt;i&gt;What strategies do you think the community could employ to address this problem and improve the (gender, and other types of) diversity in FP?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Setting up communities which aren't so hyper-intellectualized is a big step. Getting rid of all that propaganda and just treating FP like any other paradigm will do a lot to mitigate the impact of impostor syndrome and "math is hard" anti-intellectualism. It's no panacea, but it's probably the easiest thing we can tackle. Addressing the systemic issues is a lot harder.&lt;/p&gt;


&lt;p&gt;&lt;i&gt;Do you think it helps to have a women's group like Lambda Ladies? How has it been helpful for you?&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;I do think it helps. Over the years I've seen a lot of women come and go (mostly go) on Haskell Cafe. Overall I feel like the Cafe is one of the safer and more welcoming communities, but we've still had our misogynistic flareups. And after each one, I've watched the subsequent evacuation as women no longer feel quite so safe or welcome. By offering a safe space, women's groups are an important form of resistance against this sort of problem. It's a space where you don't always have to be on your guard against harassment. It's a space where you don't have to worry about how you present yourself, don't have to worry that femininity will undermine your credibility, don't have to worry about how asking "stupid" questions will affect the way people think of women as a whole.&lt;/p&gt;

&lt;p&gt;Also —we don't really do this on LL, but— women's groups can provide a safe environment for venting about the sorts of problems we encounter online, in the work force, etc. Venting is always a tricky topic, but I think the importance of venting is grossly underrated. Whatever community you're a part of, bad things are going to come up sooner or later. When that happens, having a side community where you can let off steam or discuss why the particular thing is problematic is an important way to deal with the emotional fallout of these bad things. Once you've dealt with it, you can return to the main community; but if you have nowhere to deal with it, then things build up and up until you're just done and you quit the community.&lt;/p&gt;

&lt;p&gt;In addition to providing a safe space, women's groups also serve an important role regarding announcements for jobs, conferences, etc. The announcements we get are tailored for women and so include important details like how welcoming they are of women, whether they can offer travel expenses, whether they offer child care, and so on.&lt;/p&gt;

&lt;p&gt;For me, LL has been helpful mainly as a place to witness women in FP. Just seeing other women is energizing, and keeps me interested in being out there as part of the general FP community. The bit about announcements has also been helpful.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=92722" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:81209</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/81209.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=81209"/>
    <title>Finite sets</title>
    <published>2013-01-07T01:22:57Z</published>
    <updated>2013-07-13T20:43:01Z</updated>
    <category term="coding"/>
    <category term="haskell"/>
    <category term="geek sniping"/>
    <dw:security>public</dw:security>
    <dw:reply-count>7</dw:reply-count>
    <content type="html">&lt;p&gt;So, I just encountered a &lt;a href="http://hackage.haskell.org/packages/archive/countable/0.1/doc/html/Data-Searchable.html#v:assemble"&gt;most delicious type&lt;/a&gt; the other day:&lt;p&gt;
&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;class Finite a where
    assemble :: Applicative f =&amp;gt; (a -&amp;gt; f b) -&amp;gt; f (a -&amp;gt; b)&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;What's so nice about it is that the only way you can implement it is if the type &lt;code&gt;a&lt;/code&gt; is in fact finite. (But see the notes.) So the questions are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can you see why?&lt;/li&gt;
&lt;li&gt;Can you figure out how to implement it for some chosen finite type?&lt;/li&gt;
&lt;li&gt;Can you figure out how to implement it in general, given a list of all the values? (you may assume &lt;code&gt;Eq a&lt;/code&gt; for this one)&lt;/li&gt;
&lt;li&gt;Can you figure out how to get a list of all the values, given some arbitrary implementation of &lt;code&gt;assemble&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;span class="cut-wrapper"&gt;&lt;span style="display: none;" id="span-cuttag___1" class="cuttag"&gt;&lt;/span&gt;&lt;b class="cut-open"&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class="cut-text"&gt;&lt;a href="https://winterkoninkje.dreamwidth.org/81209.html#cutid1"&gt;A trivial note&lt;/a&gt;&lt;/b&gt;&lt;b class="cut-close"&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style="display: none;" id="div-cuttag___1" aria-live="assertive"&gt;&lt;/div&gt;

&lt;span class="cut-wrapper"&gt;&lt;span style="display: none;" id="span-cuttag___2" class="cuttag"&gt;&lt;/span&gt;&lt;b class="cut-open"&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class="cut-text"&gt;&lt;a href="https://winterkoninkje.dreamwidth.org/81209.html#cutid2"&gt;A big note, also a hint perhaps&lt;/a&gt;&lt;/b&gt;&lt;b class="cut-close"&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style="display: none;" id="div-cuttag___2" aria-live="assertive"&gt;&lt;/div&gt;&lt;/p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=81209" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:72105</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/72105.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=72105"/>
    <title>Entirely pragmatic reasons to use Haskell</title>
    <published>2011-05-07T07:18:13Z</published>
    <updated>2011-05-07T07:18:13Z</updated>
    <category term="coding"/>
    <category term="java"/>
    <category term="grad school"/>
    <category term="design"/>
    <category term="haskell"/>
    <category term="pos tagging"/>
    <category term="nlp"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;I've been working on a &lt;a href="http://winterkoninkje.dreamwidth.org/68234.html"&gt;tagging library&lt;/a&gt; (and executable) for a bit over a year now. When the project started I had the advantage of being able to choose the language to do it in. Naturally I chose Haskell. There are numerous reasons for this decision, some of which have been derided as "philosophical concerns". Certainly some of the reasons why Haskell is superior to other languages do border on the philosophical. Y'know, silly little things like the belief that type systems should prevent errors rather than encouraging them to proliferate. I'm sure you've heard the arguments before. They're good arguments, and maybe they'll convince you to try out Haskell in your basement. But in many so-called "enterprise" settings, anything that even smells like it might have basis in theoretical fact is automatically wrong or irrelevant; whatever you do in the privacy of your basement is your own business, but heaven forbid it have any influence on how decisions are made in the workplace! So, here is a short list of entirely pragmatic, practical, and non-theoretical reasons why Haskell is superior to Java for implementing enterprise programs. More specifically, these are reasons why Haskell is superior for my project. Perhaps they don't matter for your project, or perhaps they'll be enough to convince your boss to let you give Haskell a try. Because design decisions are often project-specific, each point explains why they matter for Posta in particular.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Haskell has powerful frameworks for defining modular, high-performance, non-trivial parsers (e.g., &lt;a href="http://hackage.haskell.org/package/attoparsec"&gt;Attoparsec&lt;/a&gt;). In natural language processing (NLP), just like system administration, over half of the work you do involves dealing with a handful of different ad-hoc poorly defined file formats. Reading them; generating them; converting from one format to another; etc. Because every one of these formats grew out of a slow accretion of features for one particular project, they're riddled with inconsistencies, idiosyncratic magic values, corner cases, and non-context-free bits that require special handling. In Java the premiere tool (so far as I know) for defining parsers is &lt;a a="a" href="http://javacc.java.net/"&gt;JavaCC&lt;/a&gt;. (Like the C tools lex and yacc, JavaCC uses its own special syntax and requires a preprocessor, whereas Attoparsec and the like don't. However, this may be a "philosophical" issue.) However, as of last time I used it, JavaCC is designed for dealing with nice clean grammars used by programming languages and it doesn't handle inconsistent and irregular grammars very well.&lt;/li&gt;

&lt;li&gt;Posta uses a system of coroutines (called &lt;a href="http://okmij.org/ftp/Streams.html"&gt;"iteratees"&lt;/a&gt;) in order to lazily stream data from disk, through the parsers, and into the core algorithms, all while maintaining guarantees about how long resources (e.g., file handles, memory) are held for. This allows handling large files, because we don't need to keep the whole file in memory at once, either in its raw form or in the AST generated by parsing it. For modern enterprise-scale NLP, dealing with gigabyte-sized files is a requirement; because many NLP projects are not enterprise-scale, you get to spend extra time chopping up and reformatting files to fit their limitations. Last time I used JavaCC it did not support incremental parsing, and according to &lt;a href="http://javacc.java.net/doc/features.html"&gt;the advertised features&lt;/a&gt; it still doesn't. In addition, implementing coroutines is problematic because Java's security model precludes simple things like tail-call optimization--- meaning that you can only support this kind of streaming when the control flow is simple enough to avoid stack overflows.&lt;/li&gt;

&lt;li&gt;Haskell has awesome support for parallelism. One version, called &lt;a href="http://www.haskell.org/haskellwiki/Software_transactional_memory"&gt;STM&lt;/a&gt;, provides composeable atomic blocks (which matches the way we naturally think about  parallelism) combined with &lt;a href="http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html"&gt;lightweight threads&lt;/a&gt; (which make it cheap and easy). Java has no support for STM. I am unaware of any support for lightweight threads in Java. The only parallelism I'm aware of in Java is the monitor-style lock-based system with OS threads. As with all lock-based systems, it is non-composeable and difficult to get right; and as with using OS threads anywhere else, there is high overhead which removes the benefits of parallelizing many programs.&lt;/li&gt;

&lt;li&gt;Posta makes extensive use of partial evaluation for improving performance; e.g., lifting computations out of loops. When doing NLP you are often dealing with triply-nested loops, so loop-invariant code motion is essential for performance. In my benchmarks, partial evaluation reduces the total running time by 10%.  If raw numbers don't convince you: using partial evaluation allows us to keep the code legible, concise, modular, and maintainable. The primary use of partial evaluation is in a combinator library defining numerous smoothing methods for probability distributions; the results of which are called from within those triply-nested loops. Without partial evaluation, the only way to get performant code is to write a specialized version of the triply-nested loop for every different smoothing method you want to support. That means duplicating the core algorithm and a lot of tricky math, many times over. There's no way to implement this use of partial evaluation in anything resembling idiomatic Java.&lt;/li&gt;

&lt;li&gt;Posta uses an implementation of persistent asymptotically optimal priority queues which come &lt;a href="http://code.google.com/p/priority-queues/"&gt;with proofs of correctness&lt;/a&gt;. A persistent PQ is necessary for one of the tagger's core algorithms. Since the PQ methods are called from within nested loops, performance is important. Since we're dealing with giga-scale data, asymptotics are important. A log factor here or there means more than a 10% increase in total running time. In Java there's &lt;a href="http://download.oracle.com/javase/6/docs/api/java/util/PriorityQueue.html"&gt;java.util.PriorityQueue&lt;/a&gt; but it has inferior asymptotic performance guarantees and is neither persistent nor synchronized. I'm sure there are other PQ libraries out there, but I doubt anyone's implemented the exact version we need and shown their implementation to be correct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll admit I'm not up to date on state-of-the-art Java, and I'd love to be proven wrong about these things being unavailable. But a couple years ago when I returned to Java after a long time away, I learned that all the hype I'd heard about Java improving over the preceding decade was just that: hype. I have been disappointed every time I hoped Java has some trivial thing. The most recent one I've run into is Java's &lt;a href="http://winterkoninkje.dreamwidth.org/68746.html"&gt;complete refusal to believe in the existence of IPC (no, not RPC)&lt;/a&gt;, but that's hardly the tip of the iceberg.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=72105" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:71897</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/71897.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=71897"/>
    <title>Today in reblogging</title>
    <published>2011-04-05T23:35:47Z</published>
    <updated>2011-04-05T23:35:47Z</updated>
    <category term="design"/>
    <category term="python"/>
    <category term="coding"/>
    <category term="links"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;&lt;a href="http://algorithm.com.au/blog/files/immutability-blocks-lambdas-closures.php#unique-entry-id-613"&gt;Immutability and Blocks, Lambdas and Closures&lt;/a&gt; (André Pang): Mr. Python, please call the office. Your abstractions are leaking.&lt;p&gt;&lt;/p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=71897" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:71198</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/71198.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=71198"/>
    <title>Java, what's wrong with you? (pt.2)</title>
    <published>2011-04-04T01:12:36Z</published>
    <updated>2011-04-04T01:12:36Z</updated>
    <category term="coding"/>
    <category term="java"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;Last week I gave &lt;a href="http://winterkoninkje.dreamwidth.org/70921.html"&gt;a debugging problem&lt;/a&gt;. Well, now it's time for the big reveal. If you'd like to try your hand at it, you should follow that link and stop reading this post. It took me a couple weeks to figure this one out. Given the nature of the symptoms (failure only on messages of lengths 255 and 383) it was pretty clear that this was some obscure and annoying bug, like an off-by-one error. I read through the relevant code for the whole communication stack (Haskell protobufs, Haskell FIFO IO, Java FIFO IO, Java protobufs) with a inkling of what the problem might be, but I still missed it the first time through.&lt;/p&gt;

&lt;p&gt;In the hints I suggested that length 511 should also be problematic, and that we were using the length-delimited version of protobufs. For those who aren't familiar with protobufs there are only two relevant details of the encoding. The first is that length-delimited protobufs write the length before the payload (as mentioned in the hint), and the second is how that length is encoded. In order to reduce the message size, protobufs use a variable length encoding for integers. The encoding says that we read a byte at a time (little-endian order), keeping the low-order 7 bits as part of the number. If the 8th bit is unset, then we're done; if it's set, then we continue reading the next byte. Thus, the length 255 is encoded as 0xFF 0x01 (&lt;code&gt;(0xFF .&amp;amp;. 0x7F) .|. (0x01 `shiftL` 7) == 255&lt;/code&gt;), 383 is encoded as 0xFF 0x02, and 511 is encoded as 0xFF 0x03. Conversely, the non-problematic 254 is encoded as 0xFE 0x01, and 256 is encoded as 0x80 0x02.&lt;/p&gt;

&lt;p&gt;The crucial knowledge, however, is knowing that for some unfathomable reason Java decided to define their &lt;code&gt;byte&lt;/code&gt; type as a &lt;i&gt;signed&lt;/i&gt; numeric type! On the one hand, this is perverse because bytes are always used when dealing with binary formats and almost never used for actual numerical computation. On the other hand, it is sadistic because every other language in common use (and most of the ones not in common use) have unsigned bytes, so Java's choice to use signed bytes is exquisitely designed to confound any programmer who has ever used another language. More particularly, this means that the implicit conversions between bytes and other numeric types will preserve the signed value, not the representation. Thus, since 0xFF has the signed byte value -1, whenever you use this byte in, say, an &lt;code&gt;int&lt;/code&gt; context, it will be silently and implicitly converted into the int -1 as opposed to the int 255 any sane person would expect. Further, since Java comes from the C tradition of languages, it likes to use magical values to indicate errors (e.g., using -1 when only positive values are valid). I'm sure you can see where this is headed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html"&gt;InputStream&lt;/a&gt; class is one of the plethora of classes for reading from a file. In particular, it's the one used by the CLIPC library for reading from Posix &lt;a href="http://clipc.sourceforge.net/javadoc/com/lts/ipc/fifo/FIFOInputStream.html"&gt;FIFOs&lt;/a&gt;. Another awful thing about Java is that it refuses to believe in anything that systems programmers use, because by definition these things aren't portable to every operating system. I believe &lt;a href="http://winterkoninkje.dreamwidth.org/68746.html"&gt;I've alluded to this before&lt;/a&gt;. Among other things it means that Java steadfastly refuses to acknowledge the fact that separate processes can communicate without going through the network stack. If you want RPCs, then there are numerous options available to you. But heaven help you if you want to use IPC in order to avoid that overhead. And don't get me started on signal handling. Luckily for me, CLIPC does the nasty JNI coding necessary to convince Java to believe in FIFOs (and it even works for Windows FIFOs).&lt;/p&gt;

&lt;p&gt;Subclasses of InputStream provide a method which allows you to read one byte at a time from wherever it reads from. However, this method has the type &lt;code&gt;int read()&lt;/code&gt; where the return value -1 indicates end of file and values 0 through 255 indicate the byte that was read. This is just begging for bugs. You can't just return a byte, since all the bytes from 0x80 to 0xFE (-128 to -2) will be implicitly converted into invalid return values, and the byte 0xFF (-1) will be implicitly converted to EOF.&lt;/p&gt;

&lt;p&gt;Using the standard trick for amortizing IO costs, the CLIPC library reads a buffer's worth of data whenever it needs to, and then returns that data as requested. That buffer has the exceptionally reasonable type &lt;code&gt;byte[]&lt;/code&gt;. Unfortunately, when reading a single byte it does this innocuous little thing: &lt;code&gt;int returnValue = buffer[i];&lt;/code&gt;. Very easy to miss when scanning though hundreds of lines of Java, even when you have an inkling that signed bytes may be at fault. This is why implicit conversion between numeric types is Evil. Haskell does the right thing in requiring all coercions to be explicit. To fix the bug we must do: &lt;code&gt;int returnValue = ((int) buffer[i]) &amp; 0xFF;&lt;/code&gt;. Unfortunately, the buffer field is private in FIFOInputStream so I can't make a subclass to fix the bug.&lt;/p&gt;

&lt;p&gt;Surprisingly, except for the interpretation of 0xFF as EOF when reading the length header, Google's protobuf code works perfectly fine with all the other errorful byte values since it uses bytewise operations instead of arithmetic. And reads chunks at a time elsewhere, thus avoiding the bug. Good job Google :)&lt;/p&gt;

&lt;p&gt;I've sent a bug report to the author of CLIPC, but I've yet to hear back, and cursory googling indicates he may have dropped off the internet a couple years ago. If I haven't heard back by the time I make the first public release of &lt;a href="http://winterkoninkje.dreamwidth.org/68234.html"&gt;Posta&lt;/a&gt; (estimated mid--late May 2011), then I'll have to fork CLIPC since I don't want Posta's license to be dictated by this externality. LGPL 2.1+ is great and all, but this bug is a silly thing to base a license around.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=71198" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:70921</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/70921.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=70921"/>
    <title>Java, what's wrong with you?</title>
    <published>2011-03-28T04:10:43Z</published>
    <updated>2011-04-04T01:13:24Z</updated>
    <category term="haskell"/>
    <category term="geek sniping"/>
    <category term="coding"/>
    <category term="java"/>
    <dw:security>public</dw:security>
    <dw:reply-count>3</dw:reply-count>
    <content type="html">&lt;p&gt;I offer you a thought experiment. For your current project you've set up some inter-process communication. Nothing tricky involved, just your standard client&amp;ndash;server deal. You've even outsourced the protocol design and are using &lt;a href="http://code.google.com/p/protobuf/"&gt;Google's code&lt;/a&gt; to handle all the grody details of serializing and deserializing. Well, okay, on the server side you're using &lt;a href="http://hackage.haskell.org/package/hprotoc"&gt;someone else's code&lt;/a&gt; but it implements the same protocol, right? Now you run into a bug.&lt;/p&gt;

&lt;p&gt;The vast majority of the time everything works smoothly&amp;mdash; even verified by taking SHA1 hashes of the messages on both sides and comparing them. But every so often the Java client crashes. In particular, it crashes whenever reading a result message (from the server) of length 255 or 383 and maybe some larger sizes. It does, however, work perfectly fine for intervening message lengths (including 254 and 256). So what's wrong?&lt;/p&gt;

&lt;span class="cut-wrapper"&gt;&lt;span style="display: none;" id="span-cuttag___1" class="cuttag"&gt;&lt;/span&gt;&lt;b class="cut-open"&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class="cut-text"&gt;&lt;a href="https://winterkoninkje.dreamwidth.org/70921.html#cutid1"&gt;A hint&lt;/a&gt;&lt;/b&gt;&lt;b class="cut-close"&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style="display: none;" id="div-cuttag___1" aria-live="assertive"&gt;&lt;/div&gt;
&lt;span class="cut-wrapper"&gt;&lt;span style="display: none;" id="span-cuttag___2" class="cuttag"&gt;&lt;/span&gt;&lt;b class="cut-open"&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class="cut-text"&gt;&lt;a href="https://winterkoninkje.dreamwidth.org/70921.html#cutid2"&gt;Another hint&lt;/a&gt;&lt;/b&gt;&lt;b class="cut-close"&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style="display: none;" id="div-cuttag___2" aria-live="assertive"&gt;&lt;/div&gt;
&lt;span class="cut-wrapper"&gt;&lt;span style="display: none;" id="span-cuttag___3" class="cuttag"&gt;&lt;/span&gt;&lt;b class="cut-open"&gt;(&amp;nbsp;&lt;/b&gt;&lt;b class="cut-text"&gt;&lt;a href="https://winterkoninkje.dreamwidth.org/70921.html#cutid3"&gt;One last hint&lt;/a&gt;&lt;/b&gt;&lt;b class="cut-close"&gt;&amp;nbsp;)&lt;/b&gt;&lt;/span&gt;&lt;div style="display: none;" id="div-cuttag___3" aria-live="assertive"&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://winterkoninkje.dreamwidth.org/71198.html"&gt;Solution posted here.&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=70921" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:68746</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/68746.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=68746"/>
    <title>weekend hackathon</title>
    <published>2010-10-25T03:30:28Z</published>
    <updated>2010-10-25T21:20:05Z</updated>
    <category term="coding"/>
    <category term="grad school"/>
    <category term="java"/>
    <category term="pos tagging"/>
    <category term="nlp"/>
    <category term="haskell"/>
    <dw:security>public</dw:security>
    <dw:reply-count>0</dw:reply-count>
    <content type="html">&lt;p&gt;This weekend I've been doing a solo hackathon to try to get &lt;a href="http://winterkoninkje.dreamwidth.org/68234.html"&gt;Posta&lt;/a&gt; integrated with our variant of the Mink parser. All the core algorithms have already been implemented, so it's just been a whole lot of yak shaving. Namely, I have to define an IPC protocol for Haskell to talk to Java, implement the (Haskell) server executable and (Java) client stubs, and then try to shake the thing out to find bugs and performance holes. Ideally, by tuesday morning.&lt;/p&gt;

&lt;p&gt;Unfortunately, Java doesn't believe in inter-process communication, so all the libraries out there are for doing RPCs. Since the parser and tagger will be operating interactively, and on the same machine, it's quite silly to go through the network stack just to pass a few bytes back and forth. Thankfully I found &lt;a href="http://clipc.sourceforge.net/"&gt;CLIPC&lt;/a&gt; which should do the heavy lifting of getting Java to believe in POSIX named pipes. In order to handle the "on the wire" de/encoding, I've decided to go with Google's &lt;a href="http://code.google.com/p/protobuf/"&gt;protocol buffers&lt;/a&gt; since there's already a &lt;a href="http://hackage.haskell.org/package/hprotoc"&gt;protobuf compiler for Haskell&lt;/a&gt;. I was considering using &lt;a href="http://msgpack.org/"&gt;MessagePack&lt;/a&gt; (which also has &lt;a href="http://hackage.haskell.org/package/msgpack"&gt;Haskell bindings&lt;/a&gt;), but protobuf seemed a bit easier to install and work with.&lt;/p&gt;

&lt;p&gt;For all the plumbing code I decided to try working with iteratees, which have lots of nice performance guarantees. The protobuf libraries don't have integrated support for iteratees, but the internal model is a variant of iteratees so I was able to write some conversion functions. Attoparsec also uses an iteratee-like model internally, and there's &lt;a href="http://hackage.haskell.org/package/attoparsec-iteratee"&gt;integration code&lt;/a&gt; available. For my uses I actually need an enumeratee instead of an iteratee, so I had to roll one of my own.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TODO: (easy) move the CG2 training module into the library&lt;/li&gt;
&lt;li&gt;TODO: (low priority) write a CG3 training module&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write an unparser for TnT lexicon and trigram files&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;TODO: (easy) write function to feed trained models into the unparser&lt;/li&gt;
&lt;li&gt;TODO: (postponed) write wrapper executable to train models and print them to files&lt;/li&gt;
&lt;li&gt;TODO: (postponed) write function to read TnT parser output into models directly (the TnT file parsers were done previously)&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;choose a library for commandline argument munging&lt;/s&gt; &lt;a href="http://hackage.haskell.org/package/cmdargs"&gt;cmdargs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TODO: add commandline arguments for passing models to the server&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write protocol buffer spec for IPC protocol&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write Java client handlers for the IPCs&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;TODO: (low priority) write Haskell client handlers for debugging/verification of Java&lt;/li&gt;
&lt;li&gt;TODO: write Haskell code for dumping intern tables to files, and reading them back in&lt;/li&gt;
&lt;li&gt;TODO: write Java code for reading intern table files, so the client can dereference the ints&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write functions for converting the protobuf Get monad into an iteratee or enumeratee&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;TODO: write Haskell server handlers for the IPCs&lt;/li&gt;
&lt;li&gt;TODO: write STM code for parallelizing the tagging and IPC handling&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write function for converting attoparsec parsers into enumeratees&lt;/s&gt;&lt;/li&gt;
&lt;li&gt;TODO: (low priority) integrate attoparsec enumeratees into model training, etc, to replace top-level calls to many&lt;/li&gt;
&lt;li&gt;DONE: &lt;s&gt;write lots of other auxiliary functions for bytestring, attoparsec, and iteratee&lt;/s&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=68746" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
  <entry>
    <id>tag:dreamwidth.org,2010-05-25:518115:68234</id>
    <link rel="alternate" type="text/html" href="https://winterkoninkje.dreamwidth.org/68234.html"/>
    <link rel="self" type="text/xml" href="https://winterkoninkje.dreamwidth.org/data/atom/?itemid=68234"/>
    <title>Pre-announcing Posta: POS tagging and CCG supertagging in Haskell</title>
    <published>2010-10-02T22:00:52Z</published>
    <updated>2010-10-02T22:00:52Z</updated>
    <category term="grad school"/>
    <category term="coding"/>
    <category term="pos tagging"/>
    <category term="nlp"/>
    <category term="haskell"/>
    <dw:music>Dementia 2006-01-07 session 1 ~ DJs NoN, Wrexx, Valence</dw:music>
    <dw:security>public</dw:security>
    <dw:reply-count>2</dw:reply-count>
    <content type="html">&lt;p&gt;Classes have started up again, whence my month of absence. So I figure it's time to mention what I've been up to.&lt;/p&gt;

&lt;p&gt;Over the summer I was working on developing an HMM-based part of speech tagger in Haskell. Most NLP folks consider POS tagging to be a "solved problem", and despite growing long in the teeth &lt;a href="http://www.coli.uni-saarland.de/~thorsten/tnt/"&gt;TnT&lt;/a&gt; (which uses second-order HMMs) is still very close to state-of-the-art; so why bother? Two reasons. Contrary to public opinion, POS tagging is not a solved problem. We can get good accuracy for English which has fixed word order and impoverished morphology, but we still don't really know how to handle morphological languages with free word order. Moreover, the taggers we have, have all been tested extensively on English and similar languages, but we don't really know how well different approaches apply to, say, Turkish, Hungarian, Japanese, Korean, Tzotzil, Quechua,...&lt;/p&gt;

&lt;p&gt;The second reason is that my real goal is to handle supertagging for CCG, and in particular to do this for exploring online and interactive algorithms for tagging. Most of the current technology is focused on batch processing and off-line algorithms, which means that it isn't terribly useful for developing, say, an online system for real-time human--robot interaction, nor for exploring questions re the cognitive plausibility of something like supertagging serving a role in human processing of language. For doing this sort of research, TnT is too old and crotchety to work with, and the standard CCG supertaggers (&lt;a href="http://openccg.sourceforge.net/"&gt;OpenCCG&lt;/a&gt;, &lt;a href="http://svn.ask.it.usyd.edu.au/trac/candc"&gt;C&amp;amp;C Tools&lt;/a&gt;) are too integrated into their CCG parsing projects to be very amenable either. So, a new tagger writes I.&lt;/p&gt;

&lt;p&gt;It is well-known that many common NLP algorithms for HMMs and chart parsing can be generalized to operate over arbitrary semirings. Before realizing this, some algorithms were invented over and over, specialized to different semirings. While it's common in the lore, I've yet to see any codebase that actually takes advantage of this to provide implementations that are generic over different semirings. So one of my secondary goals has been to make this parameterization explicit, and to make sure to do so in a way that doesn't diminish the performance of the tagger. By making the code modular in this way, it should also help when implementing variations on HMMs like higher-order HMMs, autoregressive HMMs, etc. And for doing this sort of thing right, you really need a type system you can trust, which means Haskell (or Agda or Coq). Also, most of the current work has been done in imperative languages only, so using a functional language provides a whole new arena of research on optimizations and the like.&lt;/p&gt;

&lt;p&gt;So, that was the summer. Towards the end of the summer I did a writeup for it, though it's not entirely finished yet (i.e., ready for publicity/publication). I've continued developing it for my research assistanceship this year, which means integrating it with a variant of the Malt parser and seeing how well we can do online interactive semantic parsing of military data (which also presents an LM problem due to the huge number of OOVs, acronyms, and the use of terms like "green 42" as names).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="https://www.dreamwidth.org/tools/commentcount?user=winterkoninkje&amp;ditemid=68234" width="30" height="12" alt="comment count unavailable" style="vertical-align: middle;"/&gt; comments</content>
  </entry>
</feed>
