我正在使用Attoparsec,并且我想在整个解析任务中跟踪用户状态值。
我熟悉Parsec的单子(monad)函数getState,putState和ModifyState,但似乎在Attoparsec中找不到类似物。使用Attoparsec内部的某些东西或使用State monad可以做到这一点的简单方法吗?
最佳答案
您可以使用StateT s Parser
,请注意解析器中的回溯也会回滚状态,因此您只能获得在成功解析的情况下在代码路径上调用的那些有状态的操作。
{-# 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)
另外,我们可以直接使用大多数
Attoparsec
组合器,因为它们具有带有Alternative
,MonadPlus
,Applicative
或Monad
约束的泛型类型,并且StateT
为此定义了提升实例。我们可以将lift
用作基本的Parser
-s。