如何使用 Haskell 的 readFile 函数读取多个文件

How to use Haskell's readFile function for multiple files

我对IO有点了解。我知道您可以使用 readFile 来获取文件的内容。例如像这样:

main = do
    let inputFilePath = "C:\Haskell\myawesomeprogram\files\a.txt"
    content <- readFile inputFilePath
    print content

调用程序:

> runghc myawesomeprogram
"AAA"

太棒了,太棒了!现在我想从多个文件中读取内容。 我试过这样的事情:

files = ["C:\Haskell\myawesomeprogram\files\a.txt", "C:\Haskell\myawesomeprogram\files\b.txt","C:\Haskell\myawesomeprogram\files\c.txt"]


main :: IO ()
main = do
    filesContent <- readFiles files
    print filesContent

readFiles (x:xs) = do 
    content <- readFile x
    content : readFiles xs

这会给我以下错误信息:

myawesomeprogram.hs:6:21: error:
    * Couldn't match type `[]' with `IO'
      Expected type: IO String
        Actual type: [String]
    * In a stmt of a 'do' block: filesContent <- readFiles files
      In the expression:
        do filesContent <- readFiles files
           print filesContent
      In an equation for `main':
          main
            = do filesContent <- readFiles files
                 print filesContent
  |
6 |     filesContent <- readFiles files
  |                     ^^^^^^^^^^^^^^^

myawesomeprogram.hs:9:1: error:
    Couldn't match type `IO' with `[]'
    Expected type: [FilePath] -> [String]
      Actual type: [FilePath] -> IO String
  |
9 | readFiles (x:xs) = do
  | ^^^^^^^^^^^^^^^^^^^^^^^...

myawesomeprogram.hs:11:5: error:
    * Couldn't match type `[]' with `IO'
      Expected type: IO String
        Actual type: [String]
    * In a stmt of a 'do' block: content : readFiles xs
      In the expression:
        do content <- readFile x
           content : readFiles xs
      In an equation for `readFiles':
          readFiles (x : xs)
            = do content <- readFile x
                 content : readFiles xs
   |
11 |     content : readFiles xs
   |     ^^^^^^^^^^^^^^^^^^^^^^

我做错了什么,但是,我找不到正确的方法。 你能做对吗?

readFiles xs 不是列表,因此您不能在其前面添加项目。相反,它是一个 action,执行时会生成一个列表。

更具体地说,readFiles xs 的类型是 IO [String]IO 是可执行操作的类型),而列表的类型是 [String]。这就是错误消息告诉您的内容:无法将类型 IO [String][String].

匹配

所以要得到列表,你必须执行动作,就像你正在执行readFile

readFiles (x:xs) = do
    content <- readFile x
    theRest <- readFiles xs
    pure (content : theRest)

另请注意,当参数为空列表时,readFiles 不知道该怎么做。你应该在编译时得到一个警告,如果你不修复它,你会在运行时崩溃。

要修复,只需为空列表情况添加一个方程式:

readFiles [] = pure []
readFiles (x:xs) = do
    content <- readFile x
    theRest <- readFiles xs
    pure (content : theRest)