我正在努力学习使用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;
.... }
我不确定这是否与我的安装中破损的软件包有关,或者我不了解这些类型。提前谢谢!
答案 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的类型检查器很聪明,可以将int
与Integral 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