我是Haskell的新手,我很难从文件中读取文字和数字。我正在尝试创建一个读取大量数字和文本的程序并对它们进行比较,我想知道如何将它们读入列表中,所以比较它们会更容易,我认为...
假设我有一个包含以下内容的文件:
File 1:
Bill 9176
Tom 9183
Steve 4353
我希望将名称和号码读入列表,我该怎么做?
当我尝试编译此代码时,
import Text.Parsec
import Text.Parsec.String
parseNameNumber :: Parser (String, Integer)
parseNameNumber = do
spaces
name <- many1 letter
space
number <- fmap read $ many1 digit
return (name, number)
parseFile :: String -> IO ()
parseFile = do
result <- parseFromFile (parseNameNumber `sepBy` newline)
case result of
Left err -> print err
Right res -> print res
它给了我这些错误:
Couldn't match type `IO ()' with `String -> IO ()'
Expected type: IO (Either a0 a1)
-> (Either a0 a1 -> IO ()) -> String -> IO ()
Actual type: IO (Either a0 a1)
-> (Either a0 a1 -> IO ()) -> IO ()
In a stmt of a 'do' block:
result <- parseFromFile (parseNameNumber `sepBy` newline)
In the expression:
do { result <- parseFromFile (parseNameNumber `sepBy` newline);
case result of {
Left err -> print err
Right res -> print res } }
In an equation for `parseFile':
parseFile
= do { result <- parseFromFile (parseNameNumber `sepBy` newline);
case result of {
Left err -> print err
Right res -> print res } }
file.hs:14:13:
Couldn't match expected type `IO (Either a0 a1)'
with actual type `String
-> IO (Either ParseError [(String, Integer)])'
In the return type of a call of `parseFromFile'
Probable cause: `parseFromFile' is applied to too few arguments
In a stmt of a 'do' block:
result <- parseFromFile (parseNameNumber `sepBy` newline)
In the expression:
do { result <- parseFromFile (parseNameNumber `sepBy` newline);
case result of {
Left err -> print err
Right res -> print res } }
答案 0 :(得分:4)
查看您的数据。
"Bill 9176" :: String
现在回到你的元组
("Bill", 9176) :: (String, Int)
现在回到你的数据。可悲的是,它不是一个元组。但是有了一些纯粹的功能,它可能是你想要的类型。向下看,备份。你在哪?你在前面是一个在终端上运行vim的电脑屏幕。什么是read
的类型?
read :: Read a => a
回到String
。您可以使用words
拆分字符串。
words :: String -> [String]
当您的功能是数据而您的数据是功能时,任何事情都是可能的。我是一个单子。
parseLine :: String -> (String, Int)
parseLine xs = (\(n:i:_) -> (n, read i)) (words xs)
答案 1 :(得分:4)
听起来你的问题是解析,而不是读取文件。我赞成名为Parsec
的Haskell库进行解析。它可以与cabal install parsec
一起安装。然后
import Text.Parsec
import Text.Parsec.String
parseNameNumber :: Parser (String, Integer)
parseNameNumber = do
spaces
name <- many1 letter
space
number <- fmap read $ many1 digit
return (name, number)
parseFile :: String -> IO ()
parseFile s = do
result <- parseFromFile (parseNameNumber `sepBy` newline) s
case result of
Left err -> print err
Right res -> print res
当然,这可以通过使用列表操作操作字符串然后应用read
来完成,但它的稳健性要低得多。也许这太过分了,但我仍然会提到这是值得学习的东西。