<div dir="ltr"><div>These two pieces of code are not equivalent.</div><div><br></div><div>  :{</div>
     input = do<br>
       eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
       return eqatoms<br>
   :}<br><br>
   :{<br>
     main = do<br>
       eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
       Parsec.parse species "test species" eqatoms<br>
     return<br><div>
   :}</div><div><br></div><div>You will have to do something like</div><div>  :{</div><div>     main = do<br>
       eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
       let res = Parsec.parse species "test species" eqatoms</div><div>       putStrLn (show res)<br></div><div>     return</div><div>   :}</div><div><br></div><div>And you will eventually clean it up by using a case statement to distinguish between success and error.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jan 26, 2022 at 7:41 AM Roger Mason <<a href="mailto:rmason@mun.ca">rmason@mun.ca</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
Warning: long post.<br>
<br>
I've worked my way through various parsing tutorials using either Parsec<br>
or ReadP.  I reached a point where I need to try parsing one of the<br>
types of file for which I'm writing the parser.  I have written parsers<br>
for various parts of this file:<br>
<br>
eqatoms.out:<br>
======================================================<br>
<br>
Species :    1 (Si)<br>
 atom    1 is equivalent to atom(s)<br>
   1   2   3<br>
 atom    2 is equivalent to atom(s)<br>
   1   2   3<br>
 atom    3 is equivalent to atom(s)<br>
   1   2   3<br>
<br>
Species :    2 (O)<br>
 atom    1 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
 atom    2 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
 atom    3 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
 atom    4 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
 atom    5 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
 atom    6 is equivalent to atom(s)<br>
   1   2   3   4   5   6<br>
<br>
======================================================<br>
<br>
These are my imports:<br>
======================================================<br>
  import qualified Text.Parsec as Parsec<br>
<br>
  import Text.Parsec ((<?>))<br>
<br>
  import Control.Applicative<br>
<br>
  import Control.Monad.Identity (Identity)<br>
======================================================<br>
<br>
These are my parsers:<br>
======================================================<br>
   :{<br>
    species :: Parsec.Parsec String () (String,String)<br>
    species = do<br>
     --Parsec.char 'S'<br>
     Parsec.string "Species"<br>
     Parsec.spaces<br>
     Parsec.char ':'<br>
     Parsec.spaces<br>
     digits <- Parsec.many1 Parsec.digit<br>
     Parsec.spaces<br>
     Parsec.char '('<br>
     id <- Parsec.many1 Parsec.letter<br>
     return (id,digits)<br>
   :}<br>
<br>
   :{<br>
    atom = do<br>
     Parsec.spaces<br>
     Parsec.string "atom"<br>
     Parsec.spaces<br>
     digits <- Parsec.digit<br>
     return digits<br>
   :}<br>
<br>
:{<br>
  equivalents = do<br>
   Parsec.spaces<br>
   digits <- Parsec.digit<br>
   return digits<br>
:}<br>
======================================================<br>
<br>
Some simple tests:<br>
======================================================<br>
src = "oops"<br>
Parsec.parse species src "Species :    1 (Si)"<br>
<br>
Right ("Si","1")<br>
<br>
src = "Parsing_File/eqatoms.out"<br>
Parsec.parse atom src "atom    5 is equivalent to atom(s)"<br>
<br>
Right '5'<br>
<br>
src = "Parsing_File/eqatoms.out"<br>
Parsec.parse (Parsec.many1 equivalents) src "   1   2   3   4   5   6"<br>
<br>
: Right "123456"<br>
======================================================<br>
<br>
So, the individual parsers work as intended.  However, parsing an actual<br>
file does not work.<br>
<br>
I define a function to return the file contents:<br>
======================================================<br>
   :{<br>
     input = do<br>
       eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
       return eqatoms<br>
   :}<br>
======================================================<br>
<br>
A test shows that my reader works:<br>
======================================================<br>
input<br>
<br>
: Species :    1 (Si)\n atom    1 is equivalent to atom(s)\n   1   2<br>
3\n atom    2 is equivalent to atom(s)\n   1   2   3\n atom    3 is<br>
equivalent to atom(s)\n   1   2   3\n\nSpecies :    2 (O)\n atom    1 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n atom    2 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n atom    3 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n atom    4 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n atom    5 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n atom    6 is<br>
equivalent to atom(s)\n   1   2   3   4   5   6\n<br>
<br>
======================================================<br>
<br>
I attempt to parse the input:<br>
======================================================<br>
   :{<br>
     main = do<br>
     eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
     Parsec.parse species "test species" eqatoms<br>
     return<br>
   :}<br>
<br>
Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity| Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity| Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity| Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity| Prelude Parsec Text.Parsec Control.Applicative Control.Monad.Identity| <br>
<interactive>:250:3: error:<br>
    ,* Couldn't match type `Either Parsec.ParseError' with `IO'<br>
      Expected type: IO (String, String)<br>
        Actual type: Either Parsec.ParseError (String, String)<br>
    ,* In a stmt of a 'do' block:<br>
        Parsec.parse species "test species" eqatoms<br>
      In the expression:<br>
        do eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
           Parsec.parse species "test species" eqatoms<br>
           return<br>
      In an equation for `main':<br>
          main<br>
            = do eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
                 Parsec.parse species "test species" eqatoms<br>
                 return<br>
<br>
<interactive>:251:3: error:<br>
    ,* Couldn't match expected type `IO b'<br>
                  with actual type `a0 -> m0 a0'<br>
    ,* Probable cause: `return' is applied to too few arguments<br>
      In a stmt of a 'do' block: return<br>
      In the expression:<br>
        do eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
           Parsec.parse species "test species" eqatoms<br>
           return<br>
      In an equation for `main':<br>
          main<br>
            = do eqatoms <- readFile "Parsing_File/eqatoms.out"<br>
                 Parsec.parse species "test species" eqatoms<br>
                 return<br>
    ,* Relevant bindings include<br>
        main :: IO b (bound at <interactive>:248:3)<br>
======================================================<br>
<br>
Can someone please help me to get this to work?<br>
<br>
Thanks for reading to the end of this very long post.<br>
Roger<br>
_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners</a><br>
</blockquote></div>