我正在阅读有关构建解析器组合器库的教程,并且遇到了一种我不太了解的方法。
newtype Parser a = Parser {parse :: String -> [(a,String)]}
chainl :: Parser a -> Parser (a -> a -> a) -> a -> Parser a
chainl p op a = (p `chainl1` op) <|> return a
chainl1 :: Parser a -> Parser (a -> a -> a) -> Parser a
p `chainl1` op = do {a <- p; rest a}
where rest a = (do f <- op
b <- p
rest (f a b))
<|> return a
bind :: Parser a -> (a -> Parser b) -> Parser b
bind p f = Parser $ \s -> concatMap (\(a, s') -> parse (f a) s') $ parse p s
是操作符bind
的实现(>>=)
。我不太明白这个chainl1
功能是如何工作的。从我可以看到你从中提取f
然后op
将其应用于f a b
并递归,但是我不知道当它应该返回元组列表时如何从解析器中提取函数?