title: A tuple parser in Haskell
body: <p>I've been trying to learn functional parsing in Haskell, and as an exercise I want to write a simple tuple parser, using the functions <code>between</code> and <code>sepBy1</code> in <code>Text.ParserCombinators.ReadP</code>.  Essentially I want <code>tupleAsIntPair :: ReadP (Int, Int)</code>, which when parsed using <code>ReadP_to_S</code> takes a string such as <code>"(3,4)"</code> and returns the pair of integers <code>(3,4)</code> boxed in a <code>ReadS</code>.  Currently I have:</p>
  
  <pre><code>import Text.ParserCombinators.ReadP
  
  isNumericOrSep :: Char -&gt; Bool
  isNumericOrSep = flip elem $ "0123456789-, "
  
  tuplify2 :: [Int] -&gt; (Int, Int)
  tuplify2 [x,y] = (x,y)
  
  tupleAsIntPair :: ReadP (Int, Int)
  tupleAsIntPair = fmap tuplify2 parsedList 
      where   parsedList = fmap (map read) $ sepBy1 noparens sep
              noparens = between open close $ many1 (satisfy isNumericOrSep)
              open = char '('
              close = char ')'
              sep = char ','
  </code></pre>
  
  <p>However, when I try to run <code>(readP_to_S tupleAsIntPair) "(3,4)"</code>, I get a no parse error.  On the other hand, if I define <code>noparens</code> globally and run <code>(readP_to_S noparens) "(3,4)"</code>, I get <code>[("3,4","")]</code> and if I run <code>(readP_to_S $ sepBy1 (many1 $ satisfy isNumericOrSep) sep) "3,4"</code>, I get a list <code>[(["3"],",4"),(["3,"],"4"),(["3","4"],""),(["3,4"],"")]</code>, so at least the parser <code>sepBy1</code> is doing something, even though I only want the third parsing.  </p>
  
  <p>I think I'm composing the two parsers <code>between</code> and <code>sepBy1</code> incorrectly, or maybe <code>sepBy1</code> is not doing what I think it should.  How do I actually implement this tuple parser?  I would also appreciate any stylistic advice (e.g., <code>tuplify2</code> bugs me a little).</p>