[英]Haskell Parser Combinators - String function
我一直在阅读有关解析器组合器的教程,并且遇到了一个函数,在理解该函数时我需要一点帮助。
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = item `bind` \c ->
if p c
then unit c
else (Parser (\cs -> []))
char :: Char -> Parser Char
char c = satisfy (c ==)
natural :: Parser Integer
natural = read <$> some (satisfy isDigit)
string :: String -> Parser String
string [] = return []
string (c:cs) = do { char c; string cs; return (c:cs)}
我的问题是字符串函数如何工作,或者它如何终止,说我做了类似的事情:
let while_parser = string "while"
然后我用它来解析一个字符串,例如parse while_parser "while if"
,它将正确地解析我“ while”。
但是,如果我尝试parse while_parser "test
类的东西,它将返回[]。
我的问题是它怎么会失败? 当char c返回一个空列表时会发生什么?
假设您的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
。 从定义char
和随后的定义satisfy
我们看到,最终runParser (char c) input
将计算为[]
当char c
失败。 当p
为char c
时,查看>>=
的定义。 concatMap
将不做任何工作,因为列表将为空! 因此,从此以后对>>=
任何调用都只会遇到一个空列表并将其传递。
关于引用透明性的妙处之一是您可以写下表达式并通过替换定义并手动执行函数应用来对其进行求值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.