Attoparsec编译错误

时间:2013-06-14 23:29:47

标签: haskell attoparsec

我正在努力学习使用attoparsec。我正在尝试解析以下格式的文本文件:

id int
call_uuid string 30

我的代码在这里:

{-# LANGUAGE OverloadedStrings #-}

import Control.Applicative ((<$>))
import Data.Char (isDigit, isAlpha)
import Data.Attoparsec.Text (Parser, many1, letter, many', char, digit, string, 
                             (.*>), skipSpace, peekChar, decimal, 
                             isHorizontalSpace, skipWhile, parseOnly)
import qualified Data.Text.IO as T

schema :: Parser [(String, String, Maybe Int)]
schema = many1 typelines
  where
    colname = do
      c <- letter
      cs <- takeWhile (\x -> isDigit x || isAlpha x || x == '_')
      return (c:cs)

    int :: (Integral a, Read a) => Parser a
    int = read <$> decimal

    typelines = do
      cname <- colname
      skipWhile isHorizontalSpace
      tname <- takeWhile isAlpha
      skipWhile isHorizontalSpace
      c <- peekChar
      if c == '\n'
        then do { char '\n'; return (cname, tname, Nothing);}
        else do
          num <- int
          char '\n'
          return (cname, tname, num)

readDBTypes :: String -> IO [(String, String, Maybe Int)]
readDBTypes filename = do
  content <- T.readFile filename
  case (parseOnly schema content) of
    Left err -> do 
      print err
      return []
    Right v -> return v

main :: IO ()
main = do
  myLines <- readDBTypes "schema2.out"
  mapM_ print myLines

当我运行时,我得到以下编译器错误(ghc 7.4)

$ runhaskell schema.hs

schema.hs:18:13:
    Couldn't match expected type `attoparsec-0.10.4.0:Data.Attoparsec.Internal.Types.Parser
                                    Data.Text.Internal.Text t0'
                with actual type `[a0] -> [a0]'
    In the return type of a call of `takeWhile'
    Probable cause: `takeWhile' is applied to too few arguments
    In a stmt of a 'do' block:
      cs <- takeWhile (\ x -> isDigit x || isAlpha x || x == '_')
    In the expression:
      do { c <- letter;
           cs <- takeWhile (\ x -> isDigit x || isAlpha x || x == '_');
           return (c : cs) }

schema.hs:22:20:
    Could not deduce (Integral String) arising from a use of `decimal'
    from the context (Integral a, Read a)
      bound by the type signature for
                 int :: (Integral a, Read a) => Parser a
      at schema.hs:22:5-26
    Possible fix:
      add (Integral String) to the context of
        the type signature for int :: (Integral a, Read a) => Parser a
      or add an instance declaration for (Integral String)
    In the second argument of `(<$>)', namely `decimal'
    In the expression: read <$> decimal
    In an equation for `int': int = read <$> decimal

schema.hs:27:16:
    Couldn't match expected type `attoparsec-0.10.4.0:Data.Attoparsec.Internal.Types.Parser
                                    Data.Text.Internal.Text t0'
                with actual type `[a0] -> [a0]'
    In the return type of a call of `takeWhile'
    Probable cause: `takeWhile' is applied to too few arguments
    In a stmt of a 'do' block: tname <- takeWhile isAlpha
    In the expression:
      do { cname <- colname;
           skipWhile isHorizontalSpace;
           tname <- takeWhile isAlpha;
           skipWhile isHorizontalSpace;
           .... }

我不确定这是否与我的安装中破损的软件包有关,或者我不了解这些类型。提前谢谢!

2 个答案:

答案 0 :(得分:4)

此处有2个错误,首先takeWhile被前奏定义为(a -> Bool) -> [a] -> [a]。您可能希望来自takeWhile的{​​{1}},但您必须先导入该内容并隐藏前奏版本。

Data.Auttoparsec.Text

但是如果这个代码变得更大我的建议

import Prelude hiding (takeWhile)
import Data.Attoparsec.Text (takeWhile)

然后只使用import qualified Data.AttoParsec.Text (takeWhile) as AP ,因为当你不必跑来跑去寻找隐藏Prelude的内容时,它会更具可读性。

下一个AP.takeWhile将自行返回decimal所有内容,因此请勿对其进行fmap Integral a。您实际上并不需要read函数。 Haskell的类型检查器很聪明,可以将intIntegral a统一起来,所以只需使用普通的Int

答案 1 :(得分:2)

您需要从takeWhile导入Data.Attoparsec.Text,否则编译器将使用Prelude中的{。}}。

import Data.Attoparsec.Text (takeWhile)
import Prelude hiding (takeWhile)

decimal已经返回Integral a;不需要read

int :: Integral a => Parser a
int = decimal