4
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"
  ]

からList Int解析するためにパーサーをどのように実装できますか?Cons 0 (Cons 1 (Cons 2 (Cons 5 Nil)))list

ps : a を解析し[Int]て変換しない純粋なパーサーList Intが望ましいです。

4

4 に答える 4

7

このような:

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)

GHCi でのテスト:

*Main> parse parseList list
Done "" Cons 0 (Cons 1 (Cons 2 (Cons 5 Nil)))
于 2013-02-03T15:48:44.353 に答える
2

他の人が指摘しているように、実際にはリストを解析するために再帰を使用する必要はありません (使用できますが)。ただし、解析する再帰文法がある場合は、パーサーで再帰を使用するか (bzn の回答と Petr の回答を参照)、パーサーの結果を再帰できます (Markdown で見られる入れ子のようなもの)。ここで取り上げた後者については、http ://www.youtube.com/watch?v=nCwG9ijQMuQ&t=17m32s をご覧ください。

于 2013-02-05T18:03:38.903 に答える
2

int のリストから変換せずに:

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

ご覧のとおり、リスト パーサーは、解析しているデータ型とほとんど同じように見えます。

于 2013-02-03T16:06:55.877 に答える
1

私たちはこれを調べることでこれを行うことができると思いますmany'

many' :: (MonadPlus m) => m a -> m [a]
many' p = many_p
  where
    many_p = some_p `mplus` return []
    some_p = liftM2' (:) p many_p

同様に、独自のバリアントを作成できます。

many'' :: (MonadPlus m) => m a -> m (List a)
many'' p = many_p
  where
    many_p = some_p `mplus` return Nil
    some_p = liftM2 Cons p many_p

そして、それを任意のモナディックパーサーに適用します。

many'(最初のアクションの結果で厳密な独自のものを使用していることに注意してくださいliftM2'。モジュールによってエクスポートされないため、通常のアクションを使用しましたliftM2。)

または、以下を使用するより一般的なバリアントを作成できますAlternative

many'' :: (Alternative f) => f a -> f (List a)
many'' p = many_p
  where
    many_p = some_p <|> pure Nil
    some_p = Cons <$> p <*> many_p
于 2013-02-03T15:57:46.817 に答える