我有一个解析器定义为以下稍微复杂的版本:
data X = X { getX :: State ([Int], [X]) Bool }
type Parser = ParsecT Void String (State ([Int], [X]))
这个想法是我可以建立一堆我想对我的状态(the [Int]
)执行的操作,然后根据情况以任何顺序或我想要的任何时候执行它们:
-- Run the first state in the list.
executeOne :: Parser Bool
executeOne = do
s@(_, fs) <- get
let (r, s') = (flip runState s) . getX . head $ fs
put s'
return r
例如,执行的操作可能会重新排序操作堆栈或修改[Int]
.
除了设计决策(我确信有更好的方法可以做到这一点),回溯似乎try
不适用于状态。具体来说, ParsecT 的状态将回溯,但内部状态([Int]
and [X]
)不会。为什么是这样?我是在滥用 ParsecT 还是奇怪的递归X
业务把一切都搞砸了?我需要Control.Monad.State.Strict
改用吗?
编辑:要回答评论者关于示例的问题X
,这里有一个:
useless :: X
useless = X $ do
(vs, xs) <- get
if length vs >= 10
then do { put (vs, tail xs) ; return True }
else do { put (vs ++ vs, xs) ; return False }
useless
[Int]
如果它的元素少于十个,则加倍我们,并返回False
. 如果它确实有十个或更多元素,它会删除自己并返回True
。递归的强大X
之处在于它可以选择在完成后是否删除自己。