I have a parser defined as a slightly more complicated version of the following:
data X = X { getX :: State ([Int], [X]) Bool }
type Parser = ParsecT Void String (State ([Int], [X]))
The idea is that I can build up a stack of actions I want to do to my state (the [Int]
) and then execute them in any order or whenever I want, depending on the circumstances:
-- 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
For example, the action executed may reorder the stack of actions or modify the [Int]
.
Design decisions aside (I'm sure there are better ways to do this), it seems that backtracking with try
is not working with the state. Specifically, the state of the ParsecT will backtrack, but the inner state (the [Int]
and [X]
) won't. Why is this? Am I misusing ParsecT or is the strange recursive X
business screwing everything over? Do I need to use Control.Monad.State.Strict
instead?
Edit: To answer a commenter's question about an example X
, here's one:
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
doubles our [Int]
if it has less than ten elements, and returns False
. If it does have ten or more elements, it removes itself and returns True
. The power in having X
be recursive is that it can choose whether or not to remove itself after it's done.