Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse recursive data with parsec

import Data.Attoparsec.Text.Lazy
import Data.Text.Lazy.Internal (Text)
import Data.Text.Lazy (pack)

data List a = Nil | Cons a (List a)

list :: Text
list = pack $ unlines
  [ "0"
  , "1"
  , "2"
  , "5"
  ]

How can List Int parser coud be implemented to parse Cons 0 (Cons 1 (Cons 2 (Cons 5 Nil))) from list?

ps: pure parser without parsing a [Int] and converting it to List Int is preferable.

like image 415
ДМИТРИЙ МАЛИКОВ Avatar asked Dec 16 '22 14:12

ДМИТРИЙ МАЛИКОВ


2 Answers

Like this:

import Control.Applicative
-- rest of imports as in question

data List a = Nil | Cons a (List a)
  deriving Show -- for testing

-- definition of list as in question

parseList :: Parser (List Int)
parseList = foldr Cons Nil <$> many (decimal <* endOfLine)

Testing in GHCi:

*Main> parse parseList list
Done "" Cons 0 (Cons 1 (Cons 2 (Cons 5 Nil)))
like image 145
kosmikus Avatar answered Dec 18 '22 03:12

kosmikus


Without converting it from a list of ints:

import Data.Attoparsec.Text.Lazy
import Data.Text.Lazy (Text, pack)
import Control.Applicative

data List a = Nil | Cons a (List a)
  deriving Show

input :: Text
input = pack $ unlines [ "0", "1", "2", "5"]

list :: Parser (List Int)
list = cons <|> nil
  where
    cons = Cons <$> (decimal <* endOfLine) <*> list
    nil  = pure Nil 

main = print $ parse list input

As you can see, the list parser almost looks exactly like the datatype it's parsing.

like image 42
bzn Avatar answered Dec 18 '22 04:12

bzn