为整数编写解析器 - 类型错误
Writing Parser for Integer - Type Error
给定以下 Parser
定义(来自宾夕法尼亚大学 Brent Yorgey 教授 class):
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing -- fail on the empty input
f (x:xs) -- check if x satisfies the predicate
-- if so, return x along with the remainder
-- of the input (that is, xs)
| p x = Just (x, xs)
| otherwise = Nothing -- otherwise, fail
给定 one or more of 'a'
的以下解析器:
oneOrMore :: Parser a -> Parser [a]
oneOrMore p = (:) <$> p <*> (zeroOrMore p)
而且,现在我想提取一个 Integer
或什么都不提取:
parseInteger :: String -> Maybe Integer
parseInteger = fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber))
但是我遇到了这个编译时错误:
JsonParser.hs:42:36:
Couldn't match type ‘(String, b0)’ with ‘Maybe ([Char], String)’
Expected type: String -> (String, b0)
Actual type: String -> Maybe ([Char], String)
In the second argument of ‘($)’, namely
‘runParser (oneOrMore (satisfy isNumber))’
In the expression:
fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber))
Failed, modules loaded: SExpr, Model, AParser.
*SExpr Data.Char> :t runParser
runParser :: Parser a -> String -> Maybe (a, String)
我很困惑,因为 runParser
的类型是 String -> Maybe (a, String)
。
在 Maybe (a, String)
上调用 fmap
应该将 fmap
的函数应用于 (a, String)
类型。
我错过了什么?
您需要使用 (.)
而不是 $
:
fmap (read . fst) . runParser (oneOrMore (satisfy isNumber))
或者您需要将字符串提供给 runParser
:
parseInteger s = fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber)) s
fmap (read . fst)
在这种情况下具有类型 Maybe (String, a) -> Maybe Integer
,runParser (oneOrMore (satisfy isNumber))
具有类型 String -> Maybe (String, String)
。这两个函数可以用 (.)
组合,但是 ($)
的类型是 (a -> b) -> a -> b
- 这里 a
是 Maybe (String, a)
而你在 [=24] 中提供函数=].
如果将字符串应用于此函数,则可以获得 ($)
所需的 Maybe (String, a)
。
给定以下 Parser
定义(来自宾夕法尼亚大学 Brent Yorgey 教授 class):
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing -- fail on the empty input
f (x:xs) -- check if x satisfies the predicate
-- if so, return x along with the remainder
-- of the input (that is, xs)
| p x = Just (x, xs)
| otherwise = Nothing -- otherwise, fail
给定 one or more of 'a'
的以下解析器:
oneOrMore :: Parser a -> Parser [a]
oneOrMore p = (:) <$> p <*> (zeroOrMore p)
而且,现在我想提取一个 Integer
或什么都不提取:
parseInteger :: String -> Maybe Integer
parseInteger = fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber))
但是我遇到了这个编译时错误:
JsonParser.hs:42:36:
Couldn't match type ‘(String, b0)’ with ‘Maybe ([Char], String)’
Expected type: String -> (String, b0)
Actual type: String -> Maybe ([Char], String)
In the second argument of ‘($)’, namely
‘runParser (oneOrMore (satisfy isNumber))’
In the expression:
fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber))
Failed, modules loaded: SExpr, Model, AParser.
*SExpr Data.Char> :t runParser
runParser :: Parser a -> String -> Maybe (a, String)
我很困惑,因为 runParser
的类型是 String -> Maybe (a, String)
。
在 Maybe (a, String)
上调用 fmap
应该将 fmap
的函数应用于 (a, String)
类型。
我错过了什么?
您需要使用 (.)
而不是 $
:
fmap (read . fst) . runParser (oneOrMore (satisfy isNumber))
或者您需要将字符串提供给 runParser
:
parseInteger s = fmap (read . fst) $ runParser (oneOrMore (satisfy isNumber)) s
fmap (read . fst)
在这种情况下具有类型 Maybe (String, a) -> Maybe Integer
,runParser (oneOrMore (satisfy isNumber))
具有类型 String -> Maybe (String, String)
。这两个函数可以用 (.)
组合,但是 ($)
的类型是 (a -> b) -> a -> b
- 这里 a
是 Maybe (String, a)
而你在 [=24] 中提供函数=].
如果将字符串应用于此函数,则可以获得 ($)
所需的 Maybe (String, a)
。