gpt4 book ai didi

haskell - Megaparsec,使用 StateT 和 ParsecT 回溯用户状态

转载 作者:行者123 更新时间:2023-12-04 12:39:54 26 4
gpt4 key购买 nike

使用 Megaparsec 5。
关注 this guide ,我可以通过结合 StateT 来实现回溯用户状态和 ParsecT (未定义的类型应该是明显的/不相关的):

type MyParser a = StateT UserState (ParsecT Dec T.Text Identity) a

如果我运行解析器 p :: MyParser a , 像这样:
parsed = runParser (runStateT p initialUserState) "" input
parsed的类型是:
Either (ParseError Char Dec) (a, UserState)

这意味着,如果出现错误,用户状态将丢失。

有没有办法在这两种情况下都有它?

编辑:
如果出现错误,我是否可以使用自定义错误组件而不是 Dec(5.0 中引入的功能)并将用户状态封装在那里?

最佳答案

您可以将自定义错误组件与 observing 结合使用。用于此目的的函数(参见 this great post 了解更多信息):

{-# LANGUAGE RecordWildCards #-}

module Main where

import Text.Megaparsec
import qualified Data.Set as Set
import Control.Monad.State.Lazy

data MyState = MyState Int deriving (Ord, Eq, Show)
data MyErrorComponent = MyErrorComponent (Maybe MyState) deriving (Ord, Eq, Show)

instance ErrorComponent MyErrorComponent where
representFail _ = MyErrorComponent Nothing
representIndentation _ _ _= MyErrorComponent Nothing

type Parser = StateT MyState (Parsec MyErrorComponent String)

trackState :: Parser a -> Parser a
trackState parser = do
result <- observing parser -- run parser but don't fail right away
case result of
Right x -> return x -- if it succeeds we're done here
Left ParseError {..} -> do
state <- get -- read the current state to add it to the error component
failure errorUnexpected errorExpected $
if Set.null errorCustom then Set.singleton (MyErrorComponent $ Just state) else errorCustom

在上面的片段中, observing功能有点像 try/ catch捕获解析错误的 block ,然后读取当前状态并将其添加到自定义错误组件中。当 runParser 时依次返回自定义错误组件返回 ParseError .

下面是如何使用这个函数的演示:
a = trackState $ do
put (MyState 6)
string "foo"

b = trackState $ do
put (MyState 5)
a

main = putStrLn (show $ runParser (runStateT b (MyState 0)) "" "bar")

实际上,您可能想要做一些更聪明的事情(例如,我想您还可以添加遍历堆栈时经历的整个状态堆栈)。

关于haskell - Megaparsec,使用 StateT 和 ParsecT 回溯用户状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39798950/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com