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

时间:2018-03-15 14:52:47

标签: parsing haskell parsec

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

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 monad不是一个好主意?

2 个答案:

答案 0 :(得分:6)

ParsecT提供状态。国家提供国家。将两者结合使用可以得到两个独立的状态。

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

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

答案 1 :(得分:5)

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