Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing 无法使用do语法在解析器中获取与Haskell中的签名匹配的返回类型_Parsing_Haskell - Fatal编程技术网

Parsing 无法使用do语法在解析器中获取与Haskell中的签名匹配的返回类型

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

我正在学习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 -> []

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