我完全按照书(第一版)中的样子复制了这个例子。
书中给出了:
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)发布于 2018-03-11 02:36:28
你是正确的。解析器只是一个函数的别名,所以它使用(->)的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)发布于 2018-03-10 22:25:38
你有type Parser a = String -> [(a,String)]
因此,您使用的是(->) String Monad实例。因此,x和y的类型都是[(Char, String)]。您的代码想要return类型为([(Char,String)],[(Char,String)])的(x,y)对。因此,你得到了p :: String -> ([(Char,String)],[(Char,String)]),但是你声称p :: Parser (Char, Char)和p :: String -> [(Char, Char)]是一样的。这两个值不匹配,因此会出现类型错误。
你的问题是你把Parser当做一个单体来对待,但它不是。
(>>=) :: 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)发布于 2018-03-10 22:54:25
看起来您还没有为类型Parser定义monad实例。您可以尝试这样做,或者只使用包含书中定义的library for parsing。
https://stackoverflow.com/questions/49207052
复制相似问题