为什么在这个解析器序列中出现类型错误(Erik Meijer第8讲)? [英] Why am I getting a type error in this sequence of parsers (lecture 8 by Erik Meijer)?

查看:132
本文介绍了为什么在这个解析器序列中出现类型错误(Erik Meijer第8讲)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在观看Erik Meijer的演讲系列函数式编程基础知识(Graham Hutton的幻灯片)。

第8讲(关于功能解析器)中,在定义 Parser a 类型,引入了一些解析原语(包括 项目 return ,我命名为 return'),Erik给出了

 <$ c $>使用do语法可以将他的解析器组合成一个序列c> type Parser a = String  - > [(a,String)] 

item :: Parser Char
item = \inp - > case $ in
[] - > []
(x:xs) - > [(x,xs)]

return':: a - >解析器
返回'v = \inp - > [(v,inp)]

p :: Parser(Char,Char)
p = do x < - item
item
y < - item
return'(x,y)

然而,当我尝试在GHCi中加载时,以下类型的错误,我没有想到和不明白:

pre $ 无法匹配类型'[(Char ,字符串)]'与'Char'
期待的类型:字符串 - > [((Char,Char),String)]
实际类型:Parser([(Char,String)],[(Char,String)]]
在'do'返回'(x,y)
在表达式中:
do {x< - item;
项目;
y< - item;
return'(x,y)}
失败,模块加载:无。

我做错了什么?

问题在于 p 定义中的符号不​​使用您希望它使用的monad。



我可能是错的,但看起来像 p 正在使用Reader monad的一个版本。



如果你使用这个定义,你会看到 x y 不是 Char 值,但是类型为 [(Char,String)]

  import Debug.Trace 

p :: Parser(Char,Char)
p = do x < - item
y< - item
let foo = trace(x =++ show x)'a'
bar = trace(y =++ show y)'b'
return'(foo ,bar)

test = pqwe

如果你想使用 do 表示法,您应该创建 newtype data 声明为解析器,所以你可以定义e如何运行绑定操作符(>> =),例如:

  newtype Parser a = Parser {parse :: String  - > ; [(a,String)]} 

实例Monad Parser其中
return = Parser。返回'
(>> =)= ...

博客文章如何使用 newtype 定义解析器monad实例:(链接)


I'm in the process of watching the Functional Programming Fundamentals lecture series by Erik Meijer (with slides by Graham Hutton).

In lecture 8 (on functional parsers), after defining the Parser a type, introducing a few parsing primitives (including item and return, which I named return'), Erik gives a simple example of how his parsers can be combined in a sequence, using the do syntax:

type Parser a = String -> [(a,String)]

item :: Parser Char                                                  
item = \inp -> case inp of                                                   
                 []     -> []                                             
                 (x:xs) -> [(x,xs)]

return' :: a -> Parser a                                                   
return' v = \inp -> [(v,inp)]

p :: Parser (Char,Char)
p = do x <- item
       item
       y <- item
       return' (x,y)

However, when I try to load this in GHCi, I get the following type error, which I didn't expect and don't understand:

Couldn't match type ‘[(Char, String)]’ with ‘Char’
Expected type: String -> [((Char, Char), String)]
  Actual type: Parser ([(Char, String)], [(Char, String)])
In a stmt of a 'do' block: return' (x, y)
In the expression:
  do { x <- item;
       item;
       y <- item;
       return' (x, y) }
Failed, modules loaded: none.

What am I doing wrong?

解决方案

The problem is that the do notation in your definition of p is not using the monad you want it to use.

I could be wrong, but it looks like p is using a version of the Reader monad.

If you use this definition you'll see that x and y are not Char values but have type [(Char,String)]:

import Debug.Trace

p :: Parser (Char,Char)
p = do x <- item
       y <- item
       let foo = trace ("x = " ++ show x) 'a'
           bar = trace ("y = " ++ show y) 'b'
       return' (foo,bar)

test = p "qwe"

If you want to use do notation, you should create a newtype or data declaration for Parser so you can define how the bind operator (>>=) works, e.g.:

newtype Parser a = Parser { parse :: String -> [ (a,String) ] }

instance Monad Parser where
    return   = Parser . return'
    (>>=)    = ...

Here is a good blog post on how to define a parser monad instance using newtype: (link)

这篇关于为什么在这个解析器序列中出现类型错误(Erik Meijer第8讲)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆