This question might sound trivial but i am a Haskell beginner and i've read some tutorials for parsec but can't figure out how to store the result from a parser in a list (or in my case a list of list of string).
Here is the code of the parser:
-- Adapted from http://book.realworldhaskell.org/read/using-parsec.html -> ch16/csv9.hs and ch16/csv6.hs
import Text.ParserCombinators.Parsec
pgmFile = endBy line eol
line = sepBy cell (char ' ')
cell = many (noneOf " \n")
eol = try (string "\n\r")
<|> try (string "\r\n")
<|> string "\n"
<|> string "\r"
<?> "end of line"
parsePGM :: String -> Either ParseError [[String]]
parsePGM input = parse pgmFile "(unknown)" input
main =
do c <- getContents
case parse pgmFile "(stdin)" c of
Left e -> do putStrLn "Error parsing input:"
print e
Right r -> mapM_ print r
{-- /snippet all --}
returnString =
do c <- getContents
case parse pgmFile "(stdin)" c of
Left e -> do putStrLn "Error parsing input:"
print e
Right r -> r
The returnString function does not work but the main function accepts a ascii pgm file and parses it in a list of list of strings where every line is a list and the words are the content of the list. I want to store the resulting list in a variable to later work with it. So how can i do this?
I am really grateful for every help i can get!
Edit: The error message for the function returnString is:
pgmCH9.hs:32:24:
Couldn't match type β[]β with βIOβ
Expected type: IO ()
Actual type: [[[Char]]]
In the expression: r
In a case alternative: Right r -> r
I guess this is exactly what Sarah wrote in her comment. The type in the Left and Right case must be identical. The output of the main Right case looked like the list which i want to store so that is why i tried to save it with the help of a return value.
Here is the type of parse pgmFile "(stdin)":
ghci> :type parse pgmFile "(stdin)"
parse pgmFile "(stdin)" :: [Char] -> Either ParseError [[[Char]]]
Edit2: So here is the revised code with the added content based on the comments:
-- Adapted from http://book.realworldhaskell.org/read/using-parsec.html -> ch16/csv9.hs and ch16/csv6.hs
import Text.ParserCombinators.Parsec
import System.IO
--
{- A PGM file contains a header witht the type, a comment, the width and height of the picture
and the maximum value for all pixels. The picture presists of width*height pixels, each of
which is seperated by a space or the end-of-line character (eol). -}
--pgmFile :: Text.Parsec.Prim.ParsecT [Char] u Data.Functor.Identity.Identity [[[Char]]]
pgmFile = endBy line eol
-- Each line contains 1 or more pixels, separated by a space
--line :: Text.Parsec.Prim.ParsecT [Char] u Data.Functor.Identity.Identity [[Char]]
line = sepBy pixel (char ' ')
-- Each pixel contains of characters and is limited by space or a newline
--pixel :: Text.Parsec.Prim.ParsecT [Char] u Data.Functor.Identity.Identity [Char]
pixel = many (noneOf " \n")
--eol :: Text.Parsec.Prim.ParsecT [Char] u Data.Functor.Identity.Identity String
eol = try (string "\n\r")
<|> try (string "\r\n")
<|> string "\n"
<|> string "\r"
<?> "end of line"
parsePGM :: String -> Either ParseError [[String]]
parsePGM input = parse pgmFile "(unknown)" input
main :: IO ()
main =
do c <- getContents
case parse pgmFile "(stdin)" c of
Left e -> do putStrLn "Error parsing input:"
print e
Right r -> mapM_ print r
returnString :: IO ()
returnString =
do c <- readFile "test_ascii.pgm"
case parse pgmFile "(stdin)" c of
Left e -> do putStrLn "Error parsing input:"
print e
Right r -> print r