You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 04:42:49