我对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
| ^^^^^^^^^^^^^^^^^^^^^^
我正在做一件错事,然而,我看不出有什么方法可以把它做对。你能把它做对吗?
2条答案
按热度按时间lrl1mhuk1#
readFiles xs
不是一个列表,所以你不能在它前面加上一个元素,相反,它是一个 action,当执行时,它会产生一个列表。更具体地说,
readFiles xs
的类型是IO [String]
(IO
是可执行操作的类型),而列表的类型是[String]
。这就是错误消息告诉你的:无法将类型IO [String]
与[String]
匹配。因此,要获得列表,必须执行操作,就像执行
readFile
一样还要注意
readFiles
不知道当它的参数是一个空列表时该怎么做,你应该在编译时得到一个警告,如果你不修复它,你会在运行时崩溃。要解决这个问题,只需为空列表添加一个等式:
but5z9lq2#
如果你想对列表中的每一项做些什么,你可以使用
map
。然而,
map readFile files
在一个列表上只给你一个将产生它们的内容的动作列表,而不是它们的内容列表。然后有sequence
将采取一个动作列表,并将其转换为产生结果列表的操作。Map操作并对其进行排序是一个足够频繁的问题,因此将其缩短为mapM
。它位于Control.Monad
。您需要的代码如下所示:
请不要滚动自己的函数来执行此操作。