Haskell中如何遍历文件集合并调用处理函数?
Haskell处理文件列表的正确方式
错误原因
你用fmap countNumberOfWords returnDirectoryContents得到的类型是IO [IO Int]——这是一个IO动作,执行后会生成包含IO动作的列表,而非直接的计算结果列表。由于Haskell的Show类型类没有为IO Int实现实例,print无法输出这种类型的值,因此触发错误。
正确实现
要遍历IO包裹的文件列表并执行每个文件的处理动作,需要使用traverse(或等价的mapM)。它能将IO [FilePath]与FilePath -> IO Int组合,转换成IO [Int]——也就是依次执行列表中每个IO动作,最终返回包含所有结果的IO包裹列表。
补全后的完整代码示例:
import System.Directory import Data.List (isSuffixOf) returnDirectoryContents :: IO [FilePath] returnDirectoryContents = do let path = "." filter (isSuffixOf ".txt") <$> getDirectoryContents path countNumberOfWords :: FilePath -> IO Int countNumberOfWords path = do content <- readFile path return $ length $ words content -- 实现单词计数逻辑 main :: IO () main = do files <- returnDirectoryContents wordCounts <- traverse countNumberOfWords files -- 遍历并执行所有文件的计数动作 print wordCounts
也可以写成更紧凑的链式调用:
main = traverse countNumberOfWords =<< returnDirectoryContents >>= print
无结果遍历(仅执行动作)
如果不需要收集所有计数结果,只是想逐个输出每个文件的单词数,可以用traverse_(或mapM_),它会执行所有IO动作但不返回结果:
main = do files <- returnDirectoryContents traverse_ (\file -> do cnt <- countNumberOfWords file putStrLn $ file ++ " 的单词数:" ++ show cnt) files
内容的提问来源于stack exchange,提问作者Kspael
相关产品推荐
相关产品推荐

