Parsing 无法使用do语法在解析器中获取与Haskell中的签名匹配的返回类型
我正在学习Haskell并通过Graham Hutton的编程在Haskell中工作。一个星期以来,我一直被困在函数解析器的章节中。我按照示例进行操作,无法使用do语法获得与此解析器匹配的类型。代码如下:Parsing 无法使用do语法在解析器中获取与Haskell中的签名匹配的返回类型,parsing,haskell,Parsing,Haskell,我正在学习Haskell并通过Graham Hutton的编程在Haskell中工作。一个星期以来,我一直被困在函数解析器的章节中。我按照示例进行操作,无法使用do语法获得与此解析器匹配的类型。代码如下: type Parser a = String -> [(a,String)] ret :: a -> Parser a ret v = \inp -> [(v , inp)] failure :: Parser a failure = \inp -> [] ite
type Parser a = String -> [(a,String)]
ret :: a -> Parser a
ret v = \inp -> [(v , inp)]
failure :: Parser a
failure = \inp -> []
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)]
parse :: Parser a -> String -> [(a, String)]
parse p inp = p inp
p :: Parser (Char, Char)
p = do
x <- item
item
y <- item
ret (x, y)
并对解析器p进行如下修改:
getIt :: [(a,b)] -> a
getIt = \(x:xs) -> fst x
p :: Parser (Char, Char)
p = do
x <- item
item
y <- item
ret (getIt x, getIt y)
非常感谢您的帮助。如果我自己发现了什么,我会更新帖子
感谢请记住,您还不能完全使用
do
-表示法,因为正确使用do
表示法需要为newtype Parser
提供一个Monad
实例。由于您使用的是类型同义词,编译器很高兴地将Monad
实例用于(>)r
类型–这不是您想要的!在一个理想的世界里,编译器应该能够读懂您的意图并抱怨,但遗憾的是它不能
对解析器类型进行排序比对箭头类型进行排序更复杂。arrow类型不知道我们的意思是[]
失败,或者我们希望每个解析器吞下一点,然后吐出剩下的内容。因此,让我们定义一个排序运算符,如>>=
,它对我们的想法进行编码:
(>>>=)::解析器a->(a->解析器b)->解析器b
p>>>=f=\input->case parse p的输入
[] -> []
[(v,out)]->解析(f v)out
然后,让我们使用以下操作符对do
块进行去糖化:
p::解析器(Char,Char)
p=项目>>>=\x->
项目>>>=\\\->
项目>>=\y->
ret(x,y)
这样就可以进行打字检查了<代码>解析p“abcdef”=>[(('a','c'),“def”)]
此代码的功劳归于
或者
或者,我们可以跳过一点,实现Monad
实例。我们坚持这样做,这样我们就可以保持好的do
-块。第一步是使用newtype
,这样我们就可以将typeclass实例附加到我们的类型
newtype解析器a=
解析器{parse::String->[(a,String)]}
要使类型具有Monad
,它必须首先具有Functor
和Applicative
。函子很容易通过派生(函子)
来释放。Applicative有点复杂,但与我们上面编写的>>=
非常相似
newtype解析器a=
解析器{parse::String->[(a,String)]}
派生(函子)
实例应用程序解析器,其中
纯x=
解析器(\inp->[(x,inp)])
左右=
解析器(\inp->case parse左inp的
[] -> []
[(a2b,s)]->s的案例分析权
[] -> []
[(a,out)]->[(a2b a,out)])
实现Monad
很容易,因为它主要涉及将我们的>>=
定义复制并粘贴到操作符实际名称的定义中,>=
:
实例Monad解析器,其中
返回=
纯净的
p>>=a2q=
解析器(\inp->case parse p inp of of
[] -> []
[(a,out)]->解析(a2qa)out)
将代码还原回完整状态:
p::解析器(Char,Char)
p=do
x相关:
Prelude> parse p "abcdef"
[(('a','c'), "def")] --Expected output according to the book
[(('a','a'), "abcdef")] --Output I get after my changes