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
相关产品推荐
相关产品推荐

