You can use StateT s Parser , just remember that rollback in the parser also rolls back the state, so you only get these actions with the state that were called in the code path with successful analysis.
{-# LANGUAGE OverloadedStrings #-} import Data.Attoparsec.ByteString.Char8 import Control.Monad.State import Control.Applicative test :: StateT Int Parser () test = do many $ choice [ (modify (+1) *> lift (string "car")), (modify (+1) *> lift (string "cat"))] pure () parseOnly (runStateT test 0) "catcatcat" -- Right ((),3)
In addition, we can use most Attoparsec harvesters Attoparsec of the box, because they have common types with the restrictions Alternative , MonadPlus , Applicative or Monad , and StateT through examples for them. We can use lift for the main Parser -s.
source share