Как сохранить результат parsec в списке в Haskell?
Этот вопрос может показаться тривиальным, но я новичок в Haskell, и я прочитал некоторые уроки для parsec, но не могу понять, как сохранить результат от парсера в списке (или в моем случае в списке списка строк).
Вот код парсера:
-- 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
Функция returnString не работает, но основная функция принимает файл ascii pgm и анализирует его в списке строк, где каждая строка является списком, а слова - содержимым списка. Я хочу сохранить полученный список в переменной, чтобы позже работать с ним. Так как я могу это сделать?
Я очень благодарен за каждую помощь, которую я могу получить!
Редактировать: сообщение об ошибке для функции returnString:
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
Я думаю, это именно то, что Сара написала в своем комментарии. Тип в левом и правом корпусе должен быть одинаковым. Вывод основного правого случая выглядел как список, который я хочу сохранить, поэтому я попытался сохранить его с помощью возвращаемого значения.
Вот тип синтаксического анализа pgmFile "(stdin)":
ghci> :type parse pgmFile "(stdin)"
parse pgmFile "(stdin)" :: [Char] -> Either ParseError [[[Char]]]
Edit2: Итак, вот пересмотренный код с добавленным контентом на основе комментариев:
-- 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