无法从Haskell中的文件读取

时间:2013-12-09 17:40:39

标签: haskell

我是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 } }

2 个答案:

答案 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来完成,但它的稳健性要低得多。也许这太过分了,但我仍然会提到这是值得学习的东西。