我正在阅读关于monadic parser in Haskell的这篇论文,作为一个新手,我无法理解以下构造:
newtype Parser a = Parser (String -> [(a, String)])
instance Monad Parser where
return a = Parser (\cs -> [(a,cs)])
p >>= f = Parser (\cs -> concat [parse (f a) cs’ |
(a,cs’) <- parse p cs])
parse :: Parser a -> String -> [(a,String)]
parse (Parser p) = p
它在文中说:
对解析器(Parser p)= p定义的解析器使用解构函数,解析器p&gt;&gt; = f首先将解析器p应用于参数字符串cs以给出表单结果列表(a, cs'),其中a是值,cs'是字符串。对于每个这样的对,f a是应用于字符串cs'的解析器。
为什么(f a)而不是解析器?为什么传递'a'是必要的?
答案 0 :(得分:3)
使用monad (>>=)
实例化的Parser
类型具有此类型签名:
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
因此,在定义p >>= f
时,p
的类型为Parser a
,f
的类型为a -> Parser b
。这就是f a
是解析器而不是f
的原因:f
是从a
到Parser b
的函数。
之所以如此,没有它,我们可以组合解析器......但是我们永远无法在下一个解析中使用前一个解析器的结果!通过向前传递前一个解析器的结果,我们可以从多个解析器的结果中构建数据,例如:
parseTwoOf :: Parser a -> Parser (a, a)
parseTwoOf p = p >>= \first -> p >>= \second -> return (first, second)