我完全按照本书(第一个版本)中的示例复制了此示例。
书中给出:
p :: Parser (Char,Char)
p = do x <- item
item
y <- item
return (x,y)
在x上编译错误,为什么?
|
40 | p = do x <- item
| ^^^^^^^^^
:40:9: error:
* Couldn't match type `([(Char, String)], [(Char, String)])'
with `[((Char, Char), String)]'
Expected type: Parser (Char, Char)
Actual type: String -> ([(Char, String)], [(Char, String)])
* In a stmt of a 'do' block: x <- item
In the expression:
do x <- item
item
y <- item
return (x, y)
In an equation for `p':
p = do x <- item
item
y <- item
....
(deferred type error)
最佳答案
你是对的。解析器只是函数的别名,因此它使用(->)的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)
关于haskell - Haskell : Graham Hutton Book-(old-Yellow), Parsing (Ch-8),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49207052/