无法计算Haskell中解析器-uu parsinglib的最小长度

无法计算Haskell中解析器-uu parsinglib的最小长度,parsing,haskell,parsec,parser-combinators,uu-parsinglib,Parsing,Haskell,Parsec,Parser Combinators,Uu Parsinglib,让我们看看代码片段: pSegmentBegin p i = pIndentExact i *> ((:) <$> p i <*> ((pEOL *> pSegment p i) <|> pure [])) 我认为上面的解析器应该以同样的方式运行。为什么会发生这种错误 编辑 上面的例子非常简单(为了简化问题),如下所述,这里不需要使用do符号,但我希望它使用的实际情况如下: pSegmentBegin p i = do j <

让我们看看代码片段:

pSegmentBegin p i   = pIndentExact i *> ((:) <$> p i <*> ((pEOL *> pSegment p i) <|> pure []))
我认为上面的解析器应该以同样的方式运行。为什么会发生这种错误

编辑

上面的例子非常简单(为了简化问题),如下所述,这里不需要使用do符号,但我希望它使用的实际情况如下:

pSegmentBegin p i   = do
    j <- pIndentAtLast i
    (:) <$> p j <*> ((pEOL *> pSegments p j) <|> pure [])
psegmentbeginp i=do
j pSegments p j)纯[]
我注意到在do语句之前添加“addLength 1”可以解决问题,但我不确定这是否是正确的解决方案:

pSegmentBegin p i   = addLength 2 $ do
    j <- pIndentAtLast i
    (:) <$> p j <*> ((pEOL *> pSegments p j) <|> pure [])
pSegmentBegin p i=addLength 2$do
j pSegments p j)纯[]

它试图静态分析需要读取多少输入才能优化性能,但这种优化需要静态已知的解析器结构,这种解析器结构可以由
Applicative
s构建,因为解析器效果不能依赖于解析器值,例如
(>>=)
所做的

这就是当你使用
do
符号时出错的地方,它转换成一元绑定,打破了
Applicative
预测器。如果库只公开了两个接口中的一个,这样就不会发生这种错误,那就好了,但是如果在同一个解析器中同时使用两个接口,则会出现一些不一致


由于使用
do
是完全不必要的,因此您没有使用单声道接口提供的额外功能,因此最好避免使用它。

正如我多次提到的,应尽可能避免使用单声道接口。让我试着解释为什么应用程序接口是首选的

我的库的一个显著特点是,它通过插入或删除问题来执行错误更正。当然,我们可以在这里做一个有限的展望,但这将使这个过程非常昂贵。因此,我们只对三个步骤进行了有限的展望

现在假设我们必须插入一个表达式,其中一个表达式备选方案是:

expr:=“如果”expr“那么”expr“else”expr

然后,我们想排除该备选方案,因为选择该备选方案将需要插入另一个表达式等。因此,我们对备选方案进行抽象解释,并确保在抽签的情况下(即,有限的前瞻成本相等),我们采用一个非递归备选方案

不幸的是,当一个人编写一元解析器时,这个方案就失败了,因为绑定右侧的长度可能取决于左侧的结果。因此,我们发出错误消息,并请求程序员提供一些帮助,以指示此替代方案可能使用的令牌数量。实际值并不重要,只要您不为递归的内容提供有限的长度,并且可能导致无限的插入。它仅用于在插入时选择最短的备选方案


这种抽象的解释有一定的代价,如果你以一元的风格编写所有的解析器,那么这种分析不可避免地要重复一次。因此:如果有其他应用程序可供选择,请不要在使用此库时编写一元式解析器。

我在Uuparisinglib中有一个用于一元式解析器的解决方法。这是一个自我回答:


你可能会发现它很有用,

难道
(>>)
(*>)
不应该是等价的吗?有一条不成文的规则,那就是
应用程序的
单子的
实例应该匹配,否则事情就会变得混乱(比如这里),但是,如果您使用的是
Applicative
的属性,您可以在
Monad
中获得这些属性,那么就可以编写一个
Applicative
实例,而该实例不能有
Monad
。这将成为一条书面规则。您可以证明
(>>)
(*>)
的默认绑定是等效的,只需使用monad定律,并且假设在
ap=()
的假设下。谢谢您的回答:)目前我想使用“do风格的力量”(参见更新的示例)。我用正确的方法解决了吗?@Rhymoid正是假设
ap==()
导致了问题。当我们有
Applicative f=>Monad f
时,更明显的是它们应该对齐。。。但仍然只是一条不成文的规则。您需要依赖键入的内容才能进行编译器检查。谢谢!它澄清了很多。我认为在我的例子中,我必须使用一元式解析器组合器(
pSegmentBegin
消耗空格,计算新的缩进级别,然后强制下面的所有行使用此缩进),因此不可能用“纯应用程序”编写它样式根据您关于
StackOverflow
的问题-我不知道是否有任何问题订阅可用-如果有,我到目前为止还没有使用过,但我认为,在这里发布问题是一个非常好的主意-当我搜索任何关于
uu parsinglib
的内容时-我找到的唯一结果是
StackOverflow
和其他许多程序员-它比任何邮件列表都更容易访问。嗨@Doaitse!您可以通过将鼠标悬停在标签上方并单击“订阅”来获取所有未来SO问题(包括标签)的电子邮件通知。我将编辑您的问题,以清除不相关的要点,并尖锐的笑:)一切顺利。
pSegmentBegin p i   = do
    j <- pIndentAtLast i
    (:) <$> p j <*> ((pEOL *> pSegments p j) <|> pure [])
pSegmentBegin p i   = addLength 2 $ do
    j <- pIndentAtLast i
    (:) <$> p j <*> ((pEOL *> pSegments p j) <|> pure [])