为什么 runParsecT 需要两次初始用户状态?

Why does runParsecT requires the initial user state twice?

我定义了以下自定义解析器:

newtype St = St Int
type TxsParser = ParsecT String St (State St)

现在要能够 运行 这个解析器,我必须使用 runParserT 函数。

runParserT :: Stream s m t 
           => ParsecT s u m a 
           -> u 
           -> SourceName
           -> s 
           -> m (Either ParseError a) 

我的自定义解析器实例化为:

runParserT :: ParsecT String St (State St) a 
           -> St 
           -> SourceName 
           -> String 
           -> State St (Either ParseError a)

但这意味着如果我想评估 runParserT 的结果(这是一个状态 monad),我必须提供另一个初始状态(在本例中为 St 类型)。例如:

 evalState (runParserT myParser (St 0) fp input) (St 0)

虽然这行得通,但我必须重复两次状态似乎是错误的。这是否意味着混合 ParsecTState monads 不是一个好主意?

正确:混合 ParsecTStateT 不是一个好主意。 ParsecT monad 在回溯时小心地恢复其状态,这是一个封闭(或封闭)StateT 转换器不知道也不能正确处理的动作。

ParsecT 提供状态。状态提供状态。两者一起使用会给你两个独立的状态。

你必须同时初始化两者,这就是你看到它两次的原因。

如果您想要两个独立的状态源(例如一个回溯和一个不回溯),将它们一起使用没有错,但如果您只想要一个,这显然不是您要做的。