Haskell 哈斯凯尔:格雷厄姆·赫顿的书(旧黄色),语法分析(Ch-8)

Haskell 哈斯凯尔:格雷厄姆·赫顿的书(旧黄色),语法分析(Ch-8),haskell,compiler-errors,Haskell,Compiler Errors,我复制了本书(第一版)中的示例 书中给出: p :: Parser (Char,Char) p = do x <- item item y <- item return (x,y) p::解析器(Char,Char) p=dox您有类型解析器a=String->[(a,String)] 因此,您使用的是(>)字符串Monad实例。因此x具有类型[(Char,String)],y。您的代码希望返回类型为([(Char,String)

我复制了本书(第一版)中的示例

书中给出:

p :: Parser (Char,Char)

p =  do x <- item
        item
        y <- item
        return (x,y)
p::解析器(Char,Char)

p=dox您有
类型解析器a=String->[(a,String)]

因此,您使用的是
(>)字符串
Monad
实例。因此
x
具有类型
[(Char,String)]
y
。您的代码希望
返回
类型为
([(Char,String)],[(Char,String)])的一对
(x,y)
。因此您得到
p::String->([(Char,String)],[(Char,String)])
但是您声称
p::Parser(Char,Char)
p::String->[(Char,Char)]
相同。这些不匹配,因此会出现类型错误

您的问题是,您将
解析器
视为单子,但事实并非如此。具体而言,您希望:

(>>=) :: Parser a -> (a -> Parser b) -> Parser b
return :: a -> Parser a
但你有:

(>>=) :: Parser a -> ([(a,String)] -> Parser b) -> Parser b
return :: [(a,String)] -> Parser a
或者更一般地说:

(>>=) :: (String -> a) -> (a -> String -> b) -> (String -> b)
return :: a -> (String -> a)

似乎您还没有为类型
解析器定义monad实例。您可以尝试这样做,也可以只使用包含本书定义的

你说得对。解析器只是一个函数的别名,所以它使用(->)的Monad实例。这就是为什么您得到
String->([(Char,String)],[(Char,String)]
而不是
Parser(Char,Char)
String->[((Char,Char,String)]

我建议您自己创建一个新类型,并实例化Functor、Applicative和Monad,以获得预期的结果

这将完成以下工作:

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

item :: Parser Char
item = Parser $ \case
  [] -> []
  (c:cs) -> [(c, cs)]

instance Functor Parser where
  fmap f p = Parser $ \s ->
    concatMap (\(a, s) -> [(f a, s)]) $ parse p s

instance Applicative Parser where
  pure a = Parser $ \s -> [(a, s)]
  pf <*> pa = Parser $ \s ->
    concatMap
      (\(f, s') -> fmap (\(a, s'') -> (f a, s'')) (parse pa s'))
      (parse pf s)

instance Monad Parser where
  return a = Parser $ \s -> [(a, s)]
  pa >>= f = Parser $ \s ->
    concatMap (\(a, s') -> parse (f a) s') (parse pa s)

p :: Parser (Char,Char)
p =  do x <- item
        item
        y <- item
        return (x,y)
newtype解析器a=解析器{parse::String->[(a,String)]}
项::解析器字符
item=Parser$\case
[] -> []
(c:cs)->[(c,cs)]
实例函子解析器,其中
fmap f p=Parser$\s->
concatMap(\(a,s)->[(f a,s)])$parse p s
实例应用程序解析器,其中
纯a=解析器$\s->[(a,s)]
pf pa=Parser$\s->
海图
(\(f,s')->fmap(\(a,s')->(f,s'))(解析pa-s'))
(s)
实例Monad解析器,其中
返回a=Parser$\s->[(a,s)]
pa>>=f=Parser$\s->
concatMap(\(a,s')->parse(fa)s')(parse pa s)
解析器(Char,Char)

p=do x你能写下
item
的类型吗?item::Parser Char item=\inp->case inp of[]->[](x:xs)->[(x,xs)]Stephen Diehl的教程也是一个很好的资源,我想你正在使用
concatMap
来保持一致,但是你可以在你的
Functor
实例中使用普通的常规
map
fmap
而你的
实例似乎有点复杂,为什么不
concatMap(\(f,s')->fmap f pa s'))(解析pf s)
?如果你觉得自己特别傻,我猜
解析pf s>>=未经修正(翻转fmap pa)
但这完全是愚蠢的。你可以随心所欲地编写它。我只是觉得我编写它的方式对初学者来说很容易理解。函子实例看起来更简洁,如:
实例函子解析器,其中fmap f p=Parser$fmap(first f).parse p
应用程序实例:
实例应用程序解析器,其中pfpa=Parser$parse pf>=>(\(f,s')->first f parse pa s')
Monad:
实例Monad Parser,其中pa>=f=Parser$parse pa>=>(\(a,s')->parse(f a)s')
但是,我认为它在这里没有帮助
newtype Parser a = Parser { parse :: String -> [(a, String)] }

item :: Parser Char
item = Parser $ \case
  [] -> []
  (c:cs) -> [(c, cs)]

instance Functor Parser where
  fmap f p = Parser $ \s ->
    concatMap (\(a, s) -> [(f a, s)]) $ parse p s

instance Applicative Parser where
  pure a = Parser $ \s -> [(a, s)]
  pf <*> pa = Parser $ \s ->
    concatMap
      (\(f, s') -> fmap (\(a, s'') -> (f a, s'')) (parse pa s'))
      (parse pf s)

instance Monad Parser where
  return a = Parser $ \s -> [(a, s)]
  pa >>= f = Parser $ \s ->
    concatMap (\(a, s') -> parse (f a) s') (parse pa s)

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