为什么ParsecT类型有'u'参数? [英] Why does ParsecT type have 'u' argument?

查看:80
本文介绍了为什么ParsecT类型有'u'参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

parsec 软件包的文档指出通过一次计算来使用 u 参数来承载某些用户状态。但是,通过在 State monad上基于 ParsecT monad转换器可以实现相同的功能。所以如果我的解析器不是有状态的,我不需要 u ,但必须将它设置为()与parsec。添加非可选状态支持到 ParsecT

解决方案

因为 ParsecT s()(State st)a 类型的解析器的行为与 Parsec s st标识符a 当涉及到回溯时:


  • 当parsec在没有输入的失败解析之后尝试替代时,用户状态会重置。
  • >
  • 但是底层Monad m 不会回溯;保留最终解析结果的所有效果。



请考虑以下示例:

  { - #LANGUAGE FlexibleContexts# - } 
module Foo其中

导入Control.Applicative
导入Control.Monad.State
import Text.Parsec.Prim hiding((< |>),State(..))
import Text.Parsec.Error(ParseError)

tick :: MonadState Int m => ParsecT s Int m()
tick = do
lift $ modify(+1)
modifyState(+1)

tickTock :: MonadState Int m => ParsecT s Int m()
tickTock =(tick>> empty)< |>勾号

- |运行具有用户状态和基础状态monad的解析器。
-
- 例如:
- >>>运行tickTock
- (Right 1,2)
run :: ParsecT String Int(State Int)() - > (或者ParseError Int,Int)
run m = runState(runParserT(m> getState)initUserState - )initStateState
其中initUserState = 0
initStateState = 0

正如您所看到的,基本状态monad注册了两个ticks(来自两个可供选择的替代品),
,而Parsec monad变换器的用户状态只保留成功的。


Documentation for the parsec package states that u argument is used to carry some user state through monadic computation. But the same functionality can be achieved by basing ParsecT monad transformer on State monad. So if my parser is not stateful, i don't need u altogether, but have to set it to () with parsec. What's rationale for adding non-optional state support to ParsecT?

解决方案

Because a parser of type ParsecT s () (State st) a behaves differently from a parser of type Parsec s st Identity a when it comes to backtracking:

  • User state resets when parsec tries an alternative after a failing parse that consumes no input.
  • But the underlying Monad m does not backtrack; all the effects that happened on the way to a final parse result are kept.

Consider the following example:

{-# LANGUAGE FlexibleContexts #-}
module Foo where

import Control.Applicative
import Control.Monad.State
import Text.Parsec.Prim hiding ((<|>), State(..))
import Text.Parsec.Error (ParseError)

tick :: MonadState Int m => ParsecT s Int m ()
tick = do
  lift $ modify (+1)
  modifyState (+1)

tickTock :: MonadState Int m => ParsecT s Int m ()
tickTock = (tick >> empty) <|> tick

-- | run a parser that has both user state and an underlying state monad.
--
-- Example:
-- >>> run tickTock
-- (Right 1,2)
run :: ParsecT String Int (State Int) () -> (Either ParseError Int, Int)
run m = runState (runParserT (m >> getState) initUserState "-" "") initStateState
  where initUserState = 0
        initStateState = 0

As you can see, the underlying state monad registered two ticks (from both alternatives that were tried), while the user state of the Parsec monad transformer only kept the successful one.

这篇关于为什么ParsecT类型有'u'参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆