Как сохранить результат 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

0 ответов

Другие вопросы по тегам