这样做的目的是使用StateT在Haskell中实现< ++以充当解析器
import Control.Monad.State
type Parser = StateT String []
runParser :: Parser a -> String -> [(a,String)]
runParser = runStateT
parser :: (String -> [(a,String)]) -> Parser a
parser = StateT
(<++) :: Parser a -> Parser a -> Parser a
从这个基础开始,我如何实现&lt; ++以便它反映Text.ParserCombinators.ReadP中的定义
本地,独占,左偏选择:如果左解析器本地产生任何结果,则不使用右解析器。
答案 0 :(得分:3)
您的解析器是函数String -> [(a,String)]
,其中参数是初始状态。因此,让我们构造一个尝试第一个解析器的函数,如果失败则尝试第二个解析器:
(<++) :: Parser a -> Parser a -> Parser a
p1 <++ p2 =
parser $ \s0 -> -- 1. captures initial state
case runParser p1 s0 of -- 2. run first parser
(x:xs) -> x : xs -- 3. success
[] -> runParser p2 s0 -- 4. otherwise run second parser
一些解析器尝试这个
-- | Always fails
failP :: Parser a
failP = parser (const [])
-- | Parses an Int
intP :: Parser Int
intP = parser reads
按预期输出? (也许还有更具启发性的测试用例......)
λ> runParser (failP <++ intP) "2014"
[(2014,"")]
λ> runParser (intP <++ failP) "2014"
[(2014,"")]
λ> runParser (intP <++ intP) "2014"
[(2014,"")]