在第76页,我们将函数item
定义为解析器 - 一个函数,如果失败则需要String
并返回[(Char, String)]
或[]
。
在页78,我们定义了一个函数sat
,它接受一个谓词p
并“包装”一个解析器构造
p :: (Char -> Bool) -> Parser Char
sat p = do x <- item
if p x then return x else failure
我不明白的是<-
的魔力?如果item
的结果不为空,则此运算符应解包列表并从元组中获取第一项,否则它应生成不会阻塞谓词的内容。我错过了什么?
答案 0 :(得分:3)
do x <- item
if p x then return x else failure
这是
的语法糖item >>= (\x -> if p x then return x else failure)
>>=
是monadic绑定运算符。
您缺少的是:>>=
类型的Parser
定义是什么? (本书中Monad
Parser
实例的定义是什么?它将从instance Monad Parser where
开始。)
答案 1 :(得分:1)
do
表示法适用于monad运算符(>>=)
的应用程序。更准确地说,sat
的定义不符合以下定义。
sat p :: (Char -> Bool) -> Parser Char
sat p =
item >>= \x -> if p x then return x else failure
运算符(>>=)
首先将item
解析器应用于输入。正确地观察到这个解析器会产生第一个字符。然后,(>>=)
将第一个解析器的结果传递给它的第二个参数,即函数\x -> if p x then return x else failure
。此函数检查谓词是否满足输入流的第一个字符。如果满足,则该函数产生一个不消耗任何输入的解析器(return x
),结果只产生x
。如果它不满足谓词,则该函数会产生一个对任何输入都失败的解析器(failure
)。