У меня есть парсер, определенный как несколько более сложная версия следующего:
data X = X { getX :: State ([Int], [X]) Bool }
type Parser = ParsecT Void String (State ([Int], [X]))
Идея состоит в том, что я могу создать стек действий, которые я хочу выполнить с моим состоянием ([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]
и [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
быть рекурсивной в том, что он может выбирать, удалять ли себя после того, как это сделано.