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

Jul*_*ian 2 io haskell

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

main = do
    let inputFilePath = "C:\\Haskell\\myawesomeprogram\\files\\a.txt"
    content <- readFile inputFilePath
    print content
Run Code Online (Sandbox Code Playgroud)

调用程序:

> runghc myawesomeprogram
"AAA"
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

这会给我以下错误消息:

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
   |     ^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

我做错了事,但是,我找不到正确的方法。你能以正确的方式做到吗?

Fyo*_*kin 6

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

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

因此,要获取列表,您必须执行操作,就像执行操作一样readFile

readFiles (x:xs) = do
    content <- readFile x
    theRest <- readFiles xs
    pure (content : theRest)
Run Code Online (Sandbox Code Playgroud)

另请注意,readFiles当其参数为空列表时,不知道该怎么办。您应该在编译时收到有关它的警告,如果不修复它,则会在运行时崩溃。

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

readFiles [] = pure []
readFiles (x:xs) = do
    content <- readFile x
    theRest <- readFiles xs
    pure (content : theRest)
Run Code Online (Sandbox Code Playgroud)