编写解析器的整数 - 类型错误

时间:2015-02-08 16:01:03

标签: haskell

鉴于以下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)

fmap上呼叫Maybe (a, String)应将fmap的功能应用于(a, String)类型。

我错过了什么?

1 个答案:

答案 0 :(得分:3)

您需要使用(.)代替$

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 IntegerrunParser (oneOrMore (satisfy isNumber))的类型为String -> Maybe (String, String)。这两个函数可以由(.)组成,但($)的类型为(a -> b) -> a -> b - 此处aMaybe (String, a),而您在{{1}内提供函数}}

如果您将字符串应用于此功能,则可以获得Parser所需的Maybe (String, a)