Hi Dan,<br><br>thank you for the solution. It looks pretty interesting and usable, however I&#39;ll have to spend some time understanding arrows: I never had an opportunity to use them before. Anyway, it looks very close to what I actually need, and in any case much less ugly than breaking the GenParser encapsulation<br>
<br><div class="gmail_quote">2009/8/6 Dan Weston <span dir="ltr">&lt;<a href="mailto:westondan@imageworks.com">westondan@imageworks.com</a>&gt;</span><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Of course, since ParsecT s u m is a functor, feel free to use fmap instead of parsecMap. Then you don&#39;t need to import from Text.Parsec.Prim.<br>
And in hindsight, I might prefer the name (&lt;:&gt;) or cons to (&lt;&gt;) for the first function, but now I&#39;m just obsessing. :)<br><font color="#888888">
<br>
Dan</font><div><div></div><div class="h5"><br>
<br>
Dan Weston wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I think parsecMap does the job here:<br>
<br>
-----------------------<br>
import Text.ParserCombinators.Parsec hiding ((&lt;|&gt;))<br>
import Text.Parsec.Prim(parsecMap)<br>
import Control.Applicative((&lt;|&gt;))<br>
import Control.Arrow((|||),(&amp;&amp;&amp;))<br>
<br>
-- Tagged (:)<br>
(&lt;&gt;) :: Either Char Char -&gt; Either String String -&gt; Either String String<br>
Left  a &lt;&gt; Left  b = Left  (a:b)<br>
Left  a &lt;&gt; Right b = Left  (a:b)<br>
Right a &lt;&gt; Left  b = Left  (a:b)<br>
Right a &lt;&gt; Right b = Right (a:b)<br>
<br>
-- Tagged concat<br>
stringParser :: [Either Char Char] -&gt; Either String String<br>
stringParser = foldr (&lt;&gt;) (Right &quot;&quot;)<br>
<br>
-- Parse Integer if properly tagged, keeping unparsed string<br>
maybeToInteger :: Either String String -&gt; (Maybe Integer, String)<br>
maybeToInteger = (const Nothing ||| Just . read) &amp;&amp;&amp; (id ||| id)<br>
<br>
-- Tagged-choice parser<br>
intOrStringParser = parsecMap (maybeToInteger . stringParser)<br>
   $ many1 (parsecMap Right digit &lt;|&gt; parsecMap Left (noneOf &quot;;)&quot;))<br>
<br>
-- Parse between parentheses<br>
intOrStringListParser = between (char &#39;(&#39;)<br>
                                 (char &#39;)&#39;)<br>
                                 (sepBy1 intOrStringParser (char &#39;;&#39;))<br>
-----------------------<br>
<br>
Then you get a tagged version of each string, along with the string itself:<br>
<br>
*P&gt; parseTest intOrStringListParser $ &quot;(1;2w4;8;85)&quot;<br>
[(Just 1,&quot;1&quot;),(Nothing,&quot;2w4&quot;),(Just 8,&quot;8&quot;),(Just 85,&quot;85&quot;)]<br>
<br>
There may be some parsecMap-fold fusion optimization possible, though I haven&#39;t looked into that.<br>
<br>
Dan<br>
<br>
Paul Sujkov wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi everybody,<br>
<br>
suppose I have two different parsers: one just reads the string, and another one parses some values from it. E.g.:<br>
<br>
parseIntList :: Parser [Integer]<br>
parseIntList = do<br>
  char &#39;(&#39;<br>
  res &lt;- liftM (map read) (sepBy1 (many1 digit) (char &#39;;&#39;))<br>
  char &#39;)&#39;<br>
  return res<br>
<br>
parseIntString :: Parser String<br>
parseIntString = manyTill anyChar eof<br>
<br>
so for some input like this - &quot;(1;2;3;4)&quot; - I will have two different result:<br>
<br>
*Parlog&gt; parseTest parseIntList &quot;(1;2;3;4)&quot;<br>
[1,2,3,4]<br>
*Parlog&gt; parseTest parseIntString &quot;(1;2;3;4)&quot;<br>
&quot;(1;2;3;4)&quot;<br>
<br>
but the thing that I actually want is something like Parser ([Integer], String) - results from both parsers at a time, no matter whether one of them fails or not:<br>
<br>
*Parlog&gt; parseTest parseIntListAndString &quot;(1;2;3;4)&quot;<br>
([1,2,3,4], &quot;(1;2;3;4)&quot;)<br>
<br>
it is impossible at first sight, because first parser to use will consume all the input, and there will be nothing to parse for the second one<br>
<br>
Parsec contains &quot;choice&quot; function, but it is implemented via &lt;|&gt; and that is mplus - so it tries second alternative only if the first one fails. Is it possible to use two parsers for the same string (with try-like backtracking, no input actually consumed till the second parser finishes)? I can assume only dirty hacks with the GenParser internals - manual position storing and backtracking - but that is obviously not good<br>

<br>
however, my first attempt to solve the problem was kind a like that: to parse string to String, and then to use it as an input for the next level parse call:<br>
<br>
parseIntListAndString :: Parser ([Integer], String)<br>
parseIntListAndString = do<br>
  str &lt;- parseIntString<br>
  return (res str, str)<br>
      where res str = case (parse parseIntList &quot;&quot; str) of<br>
                        Left  err -&gt; []<br>
                        Right val -&gt; val<br>
<br>
but the problems with such a method began when I switched from Parser to GenParser with user state: function parseIntList have to update the state, but it can&#39;t have the same state as the parseIntListAndString any more: it has it&#39;s own. I can explicitly pass the state from parseIntListAndString to parseIntList, but I see no suitable way for the parseIntList to update it. I can return the updated state value from the parseIntList function, and call setState on a result - but it seems rather ugly to mee. However, if nothing else will do, that is an alternative<br>

<br>
it is of course possible to use two different parsers sequentially, but it is also very ineffective: I need to use such multiple parsing on a relatively small substring of the actual input, so little backtracking would be a much nicier approach. Any suggestions?<br>

<br>
-- <br>
Regards, Paul Sujkov<br>
<br>
</blockquote>
<br>
</blockquote>
<br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>Regards, Paul Sujkov<br>