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

Haskell新手求助:实现读取文件去重后写入新文件的问题

解决Haskell文件去重行并写入的问题

问题描述

需要实现功能:读取输入文件内容,去除重复行后将唯一行写入输出文件。目前读取和去重逻辑存在偏差,写入环节也遇到类型不匹配问题。

现有代码的问题分析

两段尝试代码存在以下核心问题:

  • 拆分函数误用:用words contents拆分内容,words是按空白字符拆分单词,而非按行拆分,应该用lines来获取每行的字符串列表。
  • 第一段代码的foldr错误:writeFile类型为FilePath -> String -> IO (),每次调用会覆盖目标文件,且foldr的参数类型不匹配——无法将IO ()作为累加器传递。
  • 第二段代码的类型不匹配:writeFile的第二个参数要求是String,但直接传入了[String]类型的行列表,导致类型错误。

正确实现代码

import Data.List (nub)

onlyUnique :: FilePath -> FilePath -> IO ()
onlyUnique inputFile outputFile = do
  -- 读取输入文件内容
  contents <- readFile inputFile
  -- 按行拆分、去重、重新拼接成带换行的完整字符串
  let fileLines = lines contents
      uniqueLines = nub fileLines
      outputContent = unlines uniqueLines
  -- 一次性写入输出文件
  writeFile outputFile outputContent

代码说明

  1. lines contents:将读取到的文件内容按换行符拆分为字符串列表,每个元素对应文件中的一行。
  2. nub fileLines:去除列表中的重复行,保留每行第一次出现的内容(注:nub是O(n²)复杂度,处理大文件时可改用Data.Set优化,比如Set.toList . Set.fromList fileLines)。
  3. unlines uniqueLines:将去重后的行列表重新拼接成完整字符串,每行末尾自动添加换行符,与lines是互逆操作。
  4. writeFile outputFile outputContent:一次性将拼接好的字符串写入输出文件,无需手动遍历或递归,writeFile会处理整个内容的写入逻辑。

额外说明

  • 无需判断行列表是否为空:unlines []会生成空字符串,writeFile写入空字符串会创建空文件,符合预期。
  • 若无需保留行的原始出现顺序,用Data.Set去重效率更高:
import qualified Data.Set as Set

uniqueLines = Set.toList $ Set.fromList fileLines

内容的提问来源于stack exchange,提问作者Mon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 07:20:10