我已经定义了以下自定义解析器:
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)
虽然这有效,但我必须重复两次状态似乎是错误的。这是否意味着混合ParsecT
和State
monad不是一个好主意?
答案 0 :(得分:6)
ParsecT提供状态。国家提供国家。将两者结合使用可以得到两个独立的状态。
你必须初始化两者,这就是你看两次的原因。
如果你想要两个独立的状态源(例如一个回溯状态和一个不回溯状态),将它们一起使用并没有错,但如果你只想要一个,那么这显然不是你要做的。
答案 1 :(得分:5)
正确:混合ParsecT
和StateT
不是一个好主意。 ParsecT
monad在回溯时会小心地恢复其状态,这是一个封闭的(或封闭的)StateT
变换器不能正确知道或正确处理的动作。