Parsing 如何在Haskell中组合多达n次的解析器?

Parsing 如何在Haskell中组合多达n次的解析器?,parsing,haskell,parsec,parser-combinators,trifecta,Parsing,Haskell,Parsec,Parser Combinators,Trifecta,我正在尝试在Haskell中组合解析器,这样我可以解析某些模式多达n次。为了举例说明,假设我想从输入中解析多达8个数字。我知道我可以使用Text.Parser.Combinators中的count来精确解析n个实例,例如: import Text.Parser.Char (digit) import Text.Parser.Combinators (count) eightDigits :: Parser [Char] eightDigits = count 8 digit 但

我正在尝试在Haskell中组合解析器,这样我可以解析某些模式多达n次。为了举例说明,假设我想从输入中解析多达8个数字。我知道我可以使用
Text.Parser.Combinators
中的
count
来精确解析n个实例,例如:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (count)

eightDigits :: Parser [Char]
eightDigits = count 8 digit
但是,如果找不到精确的8位数字,则此操作将失败。我还可以使用
some
解析一个或多个数字:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (some)

someDigits :: Parser [Char]
someDigits = some digit
上面的问题是,它可能会消耗比我想要的更多的数字。最后,我可以使用
try
,它将可能使用输入的解析器组合在一起,并在出现故障时返回到开始的位置:

import Text.Parser.Char        (digit)
import Text.Parser.Combinators (count, try)
import Control.Applicative     ((<|>))

twoOrThreeDigits :: Parser [Char]
twoOrThreeDigits = try (count 3 digit) <|> count 2 digit
import Text.Parser.Char(数字)
导入Text.Parser.Combinators(计数,重试)
导入控件。应用程序(())
twoOrThreeDigits::解析器[Char]
twoOrThreeDigits=尝试(计数3位)计数2位

虽然这可以扩展到最多8次重复,但它既不可扩展也不优雅,因此问题是如何组合解析器来解析1次到最多n次之间的任何模式?

您可以构造一个具有上限的
多个类似于
的组合器:

upto :: Int -> Parser a -> Parser [a]
upto n p | n > 0 = (:) <$> try p <*> upto (n-1) p <|> return []
upto _ _ = return []
一个简短的演示:

> map (parse (upto 8 digitChar) "") ["", "123", "1234567890"]
[Right "",Right "123",Right "12345678"]
> map (parse (upto 8 digitChar) "") ["", "123", "1234567890"]
[Right "",Right "123",Right "12345678"]