我们来评价一下pure (\x y -> (x,y)) <*> item
。第二次应用<*>
一旦我们看到第一个就会很容易:
P (\inp1 -> [(\x y -> (x,y), inp1)]) <*> item
我们替换<*>
表达式及其定义,用表达式的操作数替换定义的参数。
P (\inp2 -> case parse P (\inp1 -> [(\x y -> (x,y), inp1)]) inp2 of
[] -> []
[(g, out)] -> parse (fmap g item) out)
然后我们对fmap
表达。
P (\inp2 -> case parse P (\inp1 -> [(\x y -> (x,y), inp1)]) inp2 of
[] -> []
[(g, out)] -> parse P (\inp -> case parse item inp of
[] -> []
[(v, out)] -> [(g v, out)]) out)
现在我们可以减少前两个parse
表达式(我们将离开parse item out
稍后因为它基本上是原始的)。
P (\inp2 -> case [(\x y -> (x,y), inp2)] of
[] -> []
[(g, out)] -> case parse item out of
[] -> []
[(v, out)] -> [(g v, out)])
这么多pure (\x y -> (x,y)) <*> item
。由于您通过提升类型的二元函数创建了第一个解析器a -> b -> (a, b)
,对类型解析器的单个应用程序Parser Char
表示类型的解析器Parser (b -> (Char, b))
.
我们可以通过以下方式运行这个解析器parse
带输入的函数"abc"
。由于解析器有类型Parser (b -> (Char, b))
,这应该减少到类型的值[(b -> (Char, b), String)]
。现在让我们评估该表达式。
parse P (\inp2 -> case [(\x y -> (x,y), inp2)] of
[] -> []
[(g, out)] -> case parse item out of
[] -> []
[(v, out)] -> [(g v, out)]) "abc"
根据定义parse
这减少到
case [(\x y -> (x,y), "abc")] of
[] -> []
[(g, out)] -> case parse item out of
[] -> []
[(v, out)] -> [(g v, out)]
显然,模式在第一种情况下不匹配,但在第二种情况下匹配。我们用匹配项替换第二个表达式中的模式。
case parse item "abc" of
[] -> []
[(v, out)] -> [((\x y -> (x,y)) v, out)]
现在我们终于评估了最后一个parse
表达。parse item "abc"
明显减少为[('a', "bc")]
从定义item
.
case [('a', "bc")] of
[] -> []
[(v, out)] -> [((\x y -> (x,y)) v, out)]
同样,第二个模式匹配,我们进行替换
[((\x y -> (x,y)) 'a', "bc")]
这减少到
[(\y -> ('a', y), "bc")] :: [(b -> (Char, b), String)] -- the expected type
如果您应用相同的过程来评估第二个<*>
应用程序,并将结果放入parse
(结果)"abc"
表达式,你会发现表达式确实简化为[(('a','b'),"c")]
.