我目前正在阅读Graham Hutton撰写的Haskell编程。我被困在Parsers的章节上。其中有两个相互递归的函数定义为:
many p = many1 p +++ return []
many1 p = do v <- p
vs <- many p
return (v:vs)
many
实际上转化为这种形式:
many1 p = p >>= (\ v -> many p >>= (\ vs -> return (v : vs)))
>>=
运算符定义为:
p >>= f = P (\inp -> case parse p inp of
[] -> []
[(v,out)] -> parse (f v) out)
+++
运算符定义为:
p +++ q = P (\inp -> case parse p inp of
[] -> parse q inp
[(v,out)] -> [(v,out)])
与此问题相关的其他功能如下:
parse :: Parser a -> String -> [(a,String)]
parse (P p) inp = p inp
sat p = do x <- item
if p x then return x else failure
digit = sat isDigit
failure = P (\inp -> [])
item = P (\inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)])
return v = P (\inp -> [(v,inp)])
现在,当尝试使用many1
来解析字符串"a"
中的数字时,例如:
parse (many digit) "a"
结果为[("","a")]
。
尝试使用"a"
解析字符串many1
中的数字时:
parse (many1 digit) "a"
结果为[]
。
我想我理解为什么第二个结果。 (many1 digit)
尝试解析字符串"a"
,因此调用digit "a"
失败,因为"a"
不是数字,因此返回空列表[]
。
但是,我不理解使用(many digit)
时的第一个结果。如果(many1 digit)
返回[]
,那么显然它会失败,因此在+++
运算符中,会执行第二个case表达式。但是,当我尝试parse (return []) "a"
时,我得到的结果是[([], "a")]
。
当many
的结果为[("", "a")]
时,我无法理解many1
的结果为[]
的原因。
任何帮助表示赞赏。
P.S。我已经看过this question,但它并没有给我我想要的答案。
答案 0 :(得分:3)
如果您感到困惑,那么您在预期[("", "a")]
时会回到[([], "a")]
:
字符串是Chars列表。所以""
是一个空的Chars列表。由于[]
是任何类型的空列表,因此""
只是[]
的特例。换句话说,[] :: [Char]
完全等同于""
。
因此,由于您的解析器需要生成一个字符串,因此已知空列表的类型为[Char]
,因此打印为""
而不是[]
。