好的,所以我知道是什么Applicative
类型类包含,以及为什么它有用。但我无法完全理解如何在一个重要的示例中使用它。
例如,考虑以下相当简单的 Parsec 解析器:
integer :: Parser Integer
integer = do
many1 space
ds <- many1 digit
return $ read ds
现在如果不使用Monad
实例为Parser
?很多人声称这是可以做到的,而且是个好主意,但我不知道到底是怎么做的。
我会写
integer :: Parser Integer
integer = read <$ many1 space <*> many1 digit
有一堆左关联(如应用程序)解析器构建运算符<$>
, <*>
, <$
, <*
。最左边的东西应该是纯函数,它将组件值组合成结果值。每个运算符右侧的东西应该是一个解析器,从左到右共同给出语法的组成部分。使用哪个运算符取决于两个选择,如下所示。
the thing to the right is signal / noise
_________________________
the thing to the left is \
+-------------------
pure / | <$> <$
a parser | <*> <*
所以,既然选择了read :: String -> Integer
作为将传递解析器语义的纯函数,我们可以将前导空格分类为“噪声”,将一堆数字分类为“信号”,因此
read <$ many1 space <*> many1 digit
(..) (.........) (.........)
pure noise parser |
(.................) |
parser signal parser
(.................................)
parser
您可以将多种可能性结合起来
p1 <|> ... <|> pn
并表示不可能
empty
很少需要在解析器中命名组件,并且生成的代码看起来更像是添加了语义的语法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)