Haskell Parser Combinators - 字符串函数

时间:2016-08-16 13:12:01

标签: parsing haskell parser-combinators

我一直在阅读有关解析器组合器的教程,我遇到了一个函数,我想在尝试理解时提供一些帮助。

let while_parser = string "while"

我的问题是字符串函数是如何工作的,或者它是如何终止的,比如我做了类似的事情:

parse while_parser "while if"

然后我用它来解析一个字符串,比如说 parse while_parser "test,它会正确地解析“while”。

但是,如果我尝试Fruit Number_of_Seeds Rasp 50 Rasp 65 Straw 200 Blue 20 Straw 250 之类的东西,它会返回[]。

我的问题是它是如何失败的?当char c返回一个空列表时会发生什么?

1 个答案:

答案 0 :(得分:1)

假设您的Parser定义如下:

newtype Parser a = Parser { runParser :: String -> [(a,String)] }

然后您的Monad实例将被定义为:

instance Monad Parser where
  return x = Parser $ \input -> [(x, input)]
  p >>= f = Parser $ \input -> concatMap (\(x,s) -> runParser (f x) s) (runParser p input)

您想知道char c在这行代码中失败时会发生什么:

string (c:cs) = do { char c; string cs; return (c:cs) }

首先,让我们去除它:

string (c:cs) = char c >>= \_ -> string cs >>= \_ -> return (c:cs)

现在感兴趣的部分是char c >>= \_ -> string cs。根据{{​​1}}的定义以及随后的char定义,我们发现当satisfy失败时,最终runParser (char c) input会评估为[]。当char c>>=时,请查看p的定义。 char c将无法完成任何工作,因为列表将为空!因此,从那时起对concatMap的任何调用只会遇到一个空列表并将其传递。

参考透明度的一个奇妙之处在于,您可以通过替换定义并手动执行函数应用程序来记下您的表达式并对其进行评估。

相关问题