You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell readP库中look函数为何两种场景返回结果不同?

Haskell readP库中look与eof的行为差异解析

先看两个代码示例的核心差异及结果:

第一个代码示例(有有效输出)

pLookIf :: ReadP String 
pLookIf = do
        looked <- look
        e1 <- munch isDigit
        if looked == e1 then return ( "(" ++ e1 ++ ")" )
        else return "88"
        return looked

parseString input = readP_to_S (do                          
                        e <- pLookIf
                        eof
                        return e) input

执行结果:

ghci> parseString "8888888888888"
[("8888888888888","")]

第二个代码示例(返回空列表)

pLook :: ReadP String 
pLook = do
        looked <- look
        return looked

parseString input = readP_to_S (do                          
                        e <- pLook
                        eof
                        return e) input

执行结果:

ghci> parseString "8888888888888"
[]

原因解析

问题核心在于look、eof的行为逻辑,以及输入是否被消耗:

  • look :: ReadP String:仅读取当前剩余输入,但完全不移动输入指针、不消耗输入,执行后输入的剩余内容和位置完全不变。
  • eof :: ReadP ():要求当前剩余输入为空(即所有输入已被之前的解析器消耗完毕),否则解析直接失败。

第二个示例失败的原因

pLook只执行了look和return,全程没有任何消耗输入的操作。当后续执行eof时,剩余输入还是完整的"8888888888888",不满足eof的要求,因此整个解析器返回空列表(表示无成功解析路径)。

第一个示例成功的原因

pLookIf中,look之后执行了munch isDigit——这个解析器会消耗所有开头的数字字符,也就是把整个输入字符串全部消耗完毕。此时剩余输入为空,后续执行eof时条件满足,解析成功。

另外注意:pLookIf的do块中,最后一行return looked会覆盖前面if/else分支的return结果,因为do块的最终结果由最后一个表达式决定,所以最终返回的是最初通过look获取的完整字符串。

内容的提问来源于stack exchange,提问作者Piskator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:15:36