<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Haskell &gt; Scala &gt; (Java 7  Functional Java) &gt; Java</title>
	<atom:link href="http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/</link>
	<description>The weblog of Tony Morris</description>
	<pubDate>Tue, 06 Jan 2009 12:07:28 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6</generator>
		<item>
		<title>By: Tony Morris</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-18998</link>
		<dc:creator>Tony Morris</dc:creator>
		<pubDate>Fri, 10 Oct 2008 21:22:33 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-18998</guid>
		<description>Actually, the fact that you can post a neater solution was exactly the point, but that was lost a long time ago. The neater solution can be derived from the less neat solution by replacing lower-order expressions with higher-order expressions and kapoof! Let there be Parsec.</description>
		<content:encoded><![CDATA[<p>Actually, the fact that you can post a neater solution was exactly the point, but that was lost a long time ago. The neater solution can be derived from the less neat solution by replacing lower-order expressions with higher-order expressions and kapoof! Let there be Parsec.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Krzysztof Kościuszkiewicz</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-18110</link>
		<dc:creator>Krzysztof Kościuszkiewicz</dc:creator>
		<pubDate>Sun, 05 Oct 2008 04:05:31 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-18110</guid>
		<description>I have to admit that your Haskell solution is far from being clear, and that doesn't help you with geting your main point across.

I'm posting a shorter and less dense solution to your problem below. Hope that helps :)

&lt;code&gt;
import Control.Monad
import System.Environment

tokens = [('[',']'), ('(',')')]

parse []     = Just []
parse (c:cs) = case lookup c tokens of
    Nothing  -&#62; return (c:cs)
    Just end -&#62; parse cs &#62;&#62;= consume end &#62;&#62;= parse

consume c []     = Nothing
consume c (x:xs) = guard (c == x) &#62;&#62; return xs

main = getArgs &#62;&#62;= mapM (print . maybe False null . parse)
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>I have to admit that your Haskell solution is far from being clear, and that doesn&#8217;t help you with geting your main point across.</p>
<p>I&#8217;m posting a shorter and less dense solution to your problem below. Hope that helps <img src='http://blog.tmorris.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><code><br />
import Control.Monad<br />
import System.Environment</p>
<p>tokens = [('[',']&#8216;), (&#8217;(',&#8217;)')]</p>
<p>parse []     = Just []<br />
parse (c:cs) = case lookup c tokens of<br />
    Nothing  -&gt; return (c:cs)<br />
    Just end -&gt; parse cs &gt;&gt;= consume end &gt;&gt;= parse</p>
<p>consume c []     = Nothing<br />
consume c (x:xs) = guard (c == x) &gt;&gt; return xs</p>
<p>main = getArgs &gt;&gt;= mapM (print . maybe False null . parse)<br />
</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Steven Shaw</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-16381</link>
		<dc:creator>Steven Shaw</dc:creator>
		<pubDate>Thu, 25 Sep 2008 06:02:46 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-16381</guid>
		<description>Here's my top-down parser version in Java.

&lt;pre&gt;
public class SimpleBraceParser {

  private int index = 0;
  private String s;

  public SimpleBraceParser(String s) { this.s = s; }

  private void skip(char c) {
    ++index;
  }

  private char currentChar() {
    if (index &#60; s.length()) return s.charAt(index);
    else return ''; // Evil "sentinel" value
  }

  private void eat(char c) {
    if (currentChar() == c) {
      ++index;
      return;
    }
    throw new RuntimeException("parse error at " + index + ", expecting '" + c + "'");
  }

  public void parseRoundBrace() {
    skip('(');
    parseExpr();
    eat(')');
  }

  public void parseSquareBracket() {
    skip('[');
    parseExpr();
    eat(']');
  }

  public boolean parseExpr() {
    if (currentChar() == '(') {
      parseRoundBrace();
      return true;
    } else if (currentChar() == '[') {
      parseSquareBracket();
      return true;
    } else return false;
  }

  public void parseExprs() {
    while (parseExpr()) {
    }
  }

  public void parse() {
    parseExprs();
    if (currentChar() != '') 
      throw new RuntimeException("not terminated correctly at " + index);
  }

  static boolean reportErrors = false;

  public static void main(String[] args) {
    for (String arg : args) {
      SimpleBraceParser p = new SimpleBraceParser(arg);
      try {
        p.parse();
        System.out.println("true");
      } catch (Exception e) {
        if (reportErrors) e.printStackTrace(System.err);
        System.out.println("false");
      }
    }
  }

}
&lt;/pre&gt;

Yep, it's pretty long! I like top-down parsers as they are pretty intuitive. I'd use Antlr for any more serious parser work.

I really like the look at the Haskell version with Parsec. I tested your Haskell, Scala and Java versions along with my Java version and the Parsec version (amongst others). Your Haskell version and Parsec are very fast - Parsec is faster :). I only used /usr/bin/time to test so the JVM startup time could have hampered the Java solutions. My recursive Java version and your Scala version require stack-size increases (on my large inputs).

With the Scala version performance extremely poorly on large inputs. Pretty sure it doesn't matter if the inputs are heavily nested or not. Maybe Scala isn't the best language for functional style code. Are there any ways to improve the performance and stay functional?</description>
		<content:encoded><![CDATA[<p>Here&#8217;s my top-down parser version in Java.</p>
<pre>
public class SimpleBraceParser {

  private int index = 0;
  private String s;

  public SimpleBraceParser(String s) { this.s = s; }

  private void skip(char c) {
    ++index;
  }

  private char currentChar() {
    if (index &lt; s.length()) return s.charAt(index);
    else return ''; // Evil "sentinel" value
  }

  private void eat(char c) {
    if (currentChar() == c) {
      ++index;
      return;
    }
    throw new RuntimeException("parse error at " + index + ", expecting '" + c + "'");
  }

  public void parseRoundBrace() {
    skip('(');
    parseExpr();
    eat(')');
  }

  public void parseSquareBracket() {
    skip('[');
    parseExpr();
    eat(']');
  }

  public boolean parseExpr() {
    if (currentChar() == '(') {
      parseRoundBrace();
      return true;
    } else if (currentChar() == '[') {
      parseSquareBracket();
      return true;
    } else return false;
  }

  public void parseExprs() {
    while (parseExpr()) {
    }
  }

  public void parse() {
    parseExprs();
    if (currentChar() != '')
      throw new RuntimeException("not terminated correctly at " + index);
  }

  static boolean reportErrors = false;

  public static void main(String[] args) {
    for (String arg : args) {
      SimpleBraceParser p = new SimpleBraceParser(arg);
      try {
        p.parse();
        System.out.println("true");
      } catch (Exception e) {
        if (reportErrors) e.printStackTrace(System.err);
        System.out.println("false");
      }
    }
  }

}
</pre>
<p>Yep, it&#8217;s pretty long! I like top-down parsers as they are pretty intuitive. I&#8217;d use Antlr for any more serious parser work.</p>
<p>I really like the look at the Haskell version with Parsec. I tested your Haskell, Scala and Java versions along with my Java version and the Parsec version (amongst others). Your Haskell version and Parsec are very fast - Parsec is faster :). I only used /usr/bin/time to test so the JVM startup time could have hampered the Java solutions. My recursive Java version and your Scala version require stack-size increases (on my large inputs).</p>
<p>With the Scala version performance extremely poorly on large inputs. Pretty sure it doesn&#8217;t matter if the inputs are heavily nested or not. Maybe Scala isn&#8217;t the best language for functional style code. Are there any ways to improve the performance and stay functional?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Paul King</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-15975</link>
		<dc:creator>Paul King</dc:creator>
		<pubDate>Sat, 20 Sep 2008 15:12:35 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-15975</guid>
		<description>Groovy version of Bruce's solution:

def parse(s) { def t = s.replace("[]", "").replace("()", ""); t == s ? t : parse(t) }
args.each { println parse(it) == "" }

A little less imperative:

brackets = ["[]", "()"]
def parse2(s) { def t = brackets.inject(s){ a, b -&#62; a.replace(b,"") }; t == s ? t : parse2(t) }</description>
		<content:encoded><![CDATA[<p>Groovy version of Bruce&#8217;s solution:</p>
<p>def parse(s) { def t = s.replace(&#8221;[]&#8220;, &#8220;&#8221;).replace(&#8221;()&#8221;, &#8220;&#8221;); t == s ? t : parse(t) }<br />
args.each { println parse(it) == &#8220;&#8221; }</p>
<p>A little less imperative:</p>
<p>brackets = ["[]&#8220;, &#8220;()&#8221;]<br />
def parse2(s) { def t = brackets.inject(s){ a, b -&gt; a.replace(b,&#8221;") }; t == s ? t : parse2(t) }</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Arnaud Bailly</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13695</link>
		<dc:creator>Arnaud Bailly</dc:creator>
		<pubDate>Tue, 09 Sep 2008 19:42:04 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13695</guid>
		<description>Hello, 
Thank you for the problem. I proposed it for yesterday's dojo in Paris and we have had a very interesting session. We came up with a simple solution based on replaceAll(), like one proposal among the preceding comments, except of course we did it TDD :-) An interesting point IMHO is that all of the people around the table (about 10) did manage to help making progress towards the solution, as they were not impaired by the syntax (java) nor the environment (Eclipse), beyond the first 10 minutes setup, although most of them were not coding in java daily. I regret to say we did not achieve the same "effectiveness" with Haskell, which seems to be quite hard to grasp for most people. 

Anyway, thanks again for this nice setting. Could you be a bit more clear about the composability issues you were aiming at ?</description>
		<content:encoded><![CDATA[<p>Hello,<br />
Thank you for the problem. I proposed it for yesterday&#8217;s dojo in Paris and we have had a very interesting session. We came up with a simple solution based on replaceAll(), like one proposal among the preceding comments, except of course we did it TDD <img src='http://blog.tmorris.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> An interesting point IMHO is that all of the people around the table (about 10) did manage to help making progress towards the solution, as they were not impaired by the syntax (java) nor the environment (Eclipse), beyond the first 10 minutes setup, although most of them were not coding in java daily. I regret to say we did not achieve the same &#8220;effectiveness&#8221; with Haskell, which seems to be quite hard to grasp for most people. </p>
<p>Anyway, thanks again for this nice setting. Could you be a bit more clear about the composability issues you were aiming at ?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: aes</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13656</link>
		<dc:creator>aes</dc:creator>
		<pubDate>Tue, 09 Sep 2008 16:58:22 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13656</guid>
		<description>Trying to write a cleaner and better composed version of the above no less than triples the line count from 20 to 60. But at least it's neatly split into three 'modules':

Bracket configuration. Single point of configuration of valid opening and closing brackets in the initializer of char matching_brackets[]. Public interface:

is_opening_bracket(char c)
get_matching_closing_bracket(char c))

The parsing module. Public interface:

check(const char* str)

The main program. Public interface:

main(int argc, const char* argv[])

&lt;pre&gt;
#include &#60;stdio.h&#62;
#include &#60;assert.h&#62;

/* Section 1: configuration of brackets and accessors to it. */

/* Mapping from opening brackets to closing brackets. */
char matching_brackets[256] = {
    ['('] = ')',
    ['['] = ']'
};

int is_opening_bracket(char c)
{
    return matching_brackets[(unsigned char) c] != '';
}

char get_matching_closing_bracket(char c)
{
    assert(is_opening_bracket(c));
    return matching_brackets[(unsigned char) c];
}

/* Section 2: the parsing function itself. */

/* Parse a sequence of valid start/end brackets followed by
 * 'expected'.*/
const char* parse(char expected, const char* str)
{
    return
            /* In case of NULL input, return NULL. */
            (str == NULL) ? NULL
            /* In case of succeeded match, return the rest of the string;
             * as a special case, if 'expected' is 0, return pointer to
             * it to signal success. */
        :   (*str == expected) ? *str == 0 ? str : str + 1
            /* In case of opening bracket, parse until its matching
             * closing bracket and then continue from there */
        :   is_opening_bracket(*str) ?
            parse(expected, parse(get_matching_closing_bracket(*str), str + 1))
            /* In case of anything else, return NULL */
        :   NULL;
}

/* Is str a valid sequence of paired brackets? */
int check(const char* str)
{
    const char* result = parse(0, str);
    return (result != 0 &#38;&#38; *result == 0);
}

/* Section 3: the main program. */

/* Walk through all parameters and show parse results. */
int main(int argc, const char* argv[])
{
    while (++argv, --argc) {
        printf(check(*argv) ? "true\n" : "false\n");
    }
    return 0;
}

&lt;/pre&gt;
Unlike &lt;a href="http://www.paulgraham.com/power.html" rel="nofollow"&gt;some&lt;/a&gt; might &lt;a href="http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html" rel="nofollow"&gt;say&lt;/a&gt;, it would seem that brevity is occasionally the enemy of maintainability. Or is it just a daydream by us Blub programmers?</description>
		<content:encoded><![CDATA[<p>Trying to write a cleaner and better composed version of the above no less than triples the line count from 20 to 60. But at least it&#8217;s neatly split into three &#8216;modules&#8217;:</p>
<p>Bracket configuration. Single point of configuration of valid opening and closing brackets in the initializer of char matching_brackets[]. Public interface:</p>
<p>is_opening_bracket(char c)<br />
get_matching_closing_bracket(char c))</p>
<p>The parsing module. Public interface:</p>
<p>check(const char* str)</p>
<p>The main program. Public interface:</p>
<p>main(int argc, const char* argv[])</p>
<pre>
#include &lt;stdio.h&gt;
#include &lt;assert.h&gt;

/* Section 1: configuration of brackets and accessors to it. */

/* Mapping from opening brackets to closing brackets. */
char matching_brackets[256] = {
    ['('] = ')',
    ['['] = ']'
};

int is_opening_bracket(char c)
{
    return matching_brackets[(unsigned char) c] != '';
}

char get_matching_closing_bracket(char c)
{
    assert(is_opening_bracket(c));
    return matching_brackets[(unsigned char) c];
}

/* Section 2: the parsing function itself. */

/* Parse a sequence of valid start/end brackets followed by
 * 'expected'.*/
const char* parse(char expected, const char* str)
{
    return
            /* In case of NULL input, return NULL. */
            (str == NULL) ? NULL
            /* In case of succeeded match, return the rest of the string;
             * as a special case, if 'expected' is 0, return pointer to
             * it to signal success. */
        :   (*str == expected) ? *str == 0 ? str : str + 1
            /* In case of opening bracket, parse until its matching
             * closing bracket and then continue from there */
        :   is_opening_bracket(*str) ?
            parse(expected, parse(get_matching_closing_bracket(*str), str + 1))
            /* In case of anything else, return NULL */
        :   NULL;
}

/* Is str a valid sequence of paired brackets? */
int check(const char* str)
{
    const char* result = parse(0, str);
    return (result != 0 &amp;&amp; *result == 0);
}

/* Section 3: the main program. */

/* Walk through all parameters and show parse results. */
int main(int argc, const char* argv[])
{
    while (++argv, --argc) {
        printf(check(*argv) ? "true\n" : "false\n");
    }
    return 0;
}
</pre>
<p>Unlike <a href="http://www.paulgraham.com/power.html" onclick="javascript:pageTracker._trackPageview('/outbound/comment/www.paulgraham.com');" rel="nofollow">some</a> might <a href="http://steve-yegge.blogspot.com/2007/12/codes-worst-enemy.html" onclick="javascript:pageTracker._trackPageview('/outbound/comment/steve-yegge.blogspot.com');" rel="nofollow">say</a>, it would seem that brevity is occasionally the enemy of maintainability. Or is it just a daydream by us Blub programmers?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: aes</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13650</link>
		<dc:creator>aes</dc:creator>
		<pubDate>Tue, 09 Sep 2008 16:09:11 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13650</guid>
		<description>Spencer Tipping beat me to it with a purely functional C solution - ah well. Let's compete in brevity then.

A C solution:

&lt;pre&gt;
#include &#60;stdio.h&#62;

char matching_parens[256] = { ['('] = ')', ['['] = ']' };

const unsigned char* look_for(unsigned char expected, const unsigned char* str)
{
    return (str == 0) ? 0
        :  (*str == expected) ? *str == 0 ? str : str + 1
        :  (matching_parens[*str]) ?
           look_for(expected, look_for(matching_parens[*str], str + 1))
        :  0;
}

int main(int argc, const char* argv[]) {
    while (++argv, --argc) {
        const unsigned char* result = look_for(0, *((unsigned char**) argv));
        printf((result != 0 &#38;&#38; *result == 0) ? "true\n" : "false\n");
    }
    return 0;
}

&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>Spencer Tipping beat me to it with a purely functional C solution - ah well. Let&#8217;s compete in brevity then.</p>
<p>A C solution:</p>
<pre>
#include &lt;stdio.h&gt;

char matching_parens[256] = { ['('] = ')', ['['] = ']' };

const unsigned char* look_for(unsigned char expected, const unsigned char* str)
{
    return (str == 0) ? 0
        :  (*str == expected) ? *str == 0 ? str : str + 1
        :  (matching_parens[*str]) ?
           look_for(expected, look_for(matching_parens[*str], str + 1))
        :  0;
}

int main(int argc, const char* argv[]) {
    while (++argv, --argc) {
        const unsigned char* result = look_for(0, *((unsigned char**) argv));
        printf((result != 0 &amp;&amp; *result == 0) ? "true\n" : "false\n");
    }
    return 0;
}
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bruce Chapman</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13399</link>
		<dc:creator>Bruce Chapman</dc:creator>
		<pubDate>Tue, 09 Sep 2008 02:15:14 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13399</guid>
		<description>java - Emphasising readability over efficiency
&lt;pre&gt;
public class BracketParser {
    
    public static void main(String[] args) {
        for(String arg : args) {
            System.out.println(parse(arg));
        }
    }
    
    public static boolean parse(String arg) {
       while(arg.length() !=0 &#38;&#38; ( arg.contains("()") &#124;&#124; arg.contains("[]"))) {
            arg = arg.replace("[]", "").replace("()", "");
        }
        return arg.length() == 0;
    }
}
&lt;/pre&gt;</description>
		<content:encoded><![CDATA[<p>java - Emphasising readability over efficiency</p>
<pre>
public class BracketParser {

    public static void main(String[] args) {
        for(String arg : args) {
            System.out.println(parse(arg));
        }
    }

    public static boolean parse(String arg) {
       while(arg.length() !=0 &amp;&amp; ( arg.contains("()") || arg.contains("[]"))) {
            arg = arg.replace("[]", "").replace("()", "");
        }
        return arg.length() == 0;
    }
}
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Steve Cooper</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13100</link>
		<dc:creator>Steve Cooper</dc:creator>
		<pubDate>Mon, 08 Sep 2008 10:03:17 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13100</guid>
		<description>Oops. The code that starts that link should look like 

    bool Parse&#60;A&#62;(
      IEnumerable&#60;A&#62; inputSequence, 
      IEnumerable&#60;Pair&#60;Predicate&#60;A&#62;, Predicate&#60;A&#62;&#62; openClosePredicates)</description>
		<content:encoded><![CDATA[<p>Oops. The code that starts that link should look like </p>
<p>    bool Parse&lt;A&gt;(<br />
      IEnumerable&lt;A&gt; inputSequence,<br />
      IEnumerable&lt;Pair&lt;Predicate&lt;A&gt;, Predicate&lt;A&gt;&gt; openClosePredicates)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Steve Cooper</title>
		<link>http://blog.tmorris.net/haskell-scala-java-7-functional-java-java/#comment-13098</link>
		<dc:creator>Steve Cooper</dc:creator>
		<pubDate>Mon, 08 Sep 2008 10:01:12 +0000</pubDate>
		<guid isPermaLink="false">http://blog.tmorris.net/?p=255#comment-13098</guid>
		<description>If we're interested in composability, I'd definitely want something more general than any of the listed solutions. (I'll use what I think are haskell type annotations, but my haskell's not so hot, so excuse any mistakes. I do C# by day.)

First pass, a little more flexible, would be to have a function which accepts a set of brace pairs, with a signature like; 

    [string]-&#62;string-&#62;bool. 

Or in C#;

    bool Parse(string input, IEnumerable bracePairs)

which you partially-apply like;

    var tokens = new [] { "[]", "{}" };
    Predicate bracketParser = args =&#62; Parse(args, tokens);
    
so you can pass your list of open-close characters in. That would extend it to use any number of bracket pairs. 

More generally, though, why not extract the string data type entirely? The underlying idea, I think, is that we want to pair open and close operations on a sequence. So paren-matching is connected to these predicates (C#);

    char =&#62; char == '('
    char =&#62; char == ')'

But who cares about characters specifically? We can get to a general matcher, which will match paired open/close predicates in any sequence. I think the haskell type looks like [(a-&#62;bool, a-&#62;bool)]-&#62;a-&#62;bool. (That first type should be 'list of pairs of predicates of a'. In C#

   bool Parse&lt;A&gt;(
     IEnumerable&lt;A&gt; inputSequence, 
     IEnumerable&#60;Pair&#60;Predicate&lt;A&gt;, Predicate&lt;A&gt;&#62; openClosePredicates)

I've written a C# version which I think is fairly general. It's on another machine, but I'll post it if you're interested.

Basic idea, though, is to use a stack to match open and close predicates. So;
    
    Create a stack of close-predicates. These are, say, the close-brcakets we're waiting for,
    
    Loop through the sequence. 
    
    If you match an open-predicate to the current item (say, char =&#62; char == '(') you push the paired close-predicate (say, char =&#62; char == ')') onto the stack. 
            
    If you can match the close-predicate at the top of the stack, great -- pop it off, we've got paired brackets.
    
    Otherwise, you've got a mismatched sequence and return false. 
    
    At the end, you return true iff you've got an empty stack.

Anyway, this allows you to write general open/close parsers. If you wanted to write a parser for a VB-like language, you could pass in paired functions like 

   statement =&#62; Regex.IsMatch(statement, "if .* then")
   statement =&#62; statement == "end if"
   
working on a sequence of lines of code. 

Floating around in the back of my head, half-baked, is the idea that maybe you could combine or pass parsers to each other somehow; something like;

  vbParser = Parser.Compose(IfBlockParser, ForLoopParser, WhileLoopParser)
  
Hmm...</description>
		<content:encoded><![CDATA[<p>If we&#8217;re interested in composability, I&#8217;d definitely want something more general than any of the listed solutions. (I&#8217;ll use what I think are haskell type annotations, but my haskell&#8217;s not so hot, so excuse any mistakes. I do C# by day.)</p>
<p>First pass, a little more flexible, would be to have a function which accepts a set of brace pairs, with a signature like; </p>
<p>    [string]-&gt;string-&gt;bool. </p>
<p>Or in C#;</p>
<p>    bool Parse(string input, IEnumerable bracePairs)</p>
<p>which you partially-apply like;</p>
<p>    var tokens = new [] { &#8220;[]&#8220;, &#8220;{}&#8221; };<br />
    Predicate bracketParser = args =&gt; Parse(args, tokens);</p>
<p>so you can pass your list of open-close characters in. That would extend it to use any number of bracket pairs. </p>
<p>More generally, though, why not extract the string data type entirely? The underlying idea, I think, is that we want to pair open and close operations on a sequence. So paren-matching is connected to these predicates (C#);</p>
<p>    char =&gt; char == &#8216;(&#8217;<br />
    char =&gt; char == &#8216;)&#8217;</p>
<p>But who cares about characters specifically? We can get to a general matcher, which will match paired open/close predicates in any sequence. I think the haskell type looks like [(a-&gt;bool, a-&gt;bool)]-&gt;a-&gt;bool. (That first type should be &#8216;list of pairs of predicates of a&#8217;. In C#</p>
<p>   bool Parse<a>(<br />
     IEnumerable</a><a> inputSequence,<br />
     IEnumerable&lt;Pair&lt;Predicate</a><a>, Predicate</a><a>&gt; openClosePredicates)</p>
<p>I&#8217;ve written a C# version which I think is fairly general. It&#8217;s on another machine, but I&#8217;ll post it if you&#8217;re interested.</p>
<p>Basic idea, though, is to use a stack to match open and close predicates. So;</p>
<p>    Create a stack of close-predicates. These are, say, the close-brcakets we&#8217;re waiting for,</p>
<p>    Loop through the sequence. </p>
<p>    If you match an open-predicate to the current item (say, char =&gt; char == &#8216;(&#8217;) you push the paired close-predicate (say, char =&gt; char == &#8216;)&#8217;) onto the stack. </p>
<p>    If you can match the close-predicate at the top of the stack, great &#8212; pop it off, we&#8217;ve got paired brackets.</p>
<p>    Otherwise, you&#8217;ve got a mismatched sequence and return false. </p>
<p>    At the end, you return true iff you&#8217;ve got an empty stack.</p>
<p>Anyway, this allows you to write general open/close parsers. If you wanted to write a parser for a VB-like language, you could pass in paired functions like </p>
<p>   statement =&gt; Regex.IsMatch(statement, &#8220;if .* then&#8221;)<br />
   statement =&gt; statement == &#8220;end if&#8221;</p>
<p>working on a sequence of lines of code. </p>
<p>Floating around in the back of my head, half-baked, is the idea that maybe you could combine or pass parsers to each other somehow; something like;</p>
<p>  vbParser = Parser.Compose(IfBlockParser, ForLoopParser, WhileLoopParser)</p>
<p>Hmm&#8230;</a></p>
]]></content:encoded>
	</item>
</channel>
</rss>
