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

Haskell高阶函数实现列表去重咨询:禁用列表推导式

用高阶函数与Lambda实现列表去重

你的递归版本逻辑很清晰,现在我们可以用Haskell的高阶函数(比如foldr、any)结合Lambda表达式来重构它,完全替代手动递归:

等价的高阶函数实现

unique :: (Eq a) => [a] -> [a]
unique = foldr (\x acc -> if not (any (==x) acc) then x : acc else acc) []

逐行解释

  1. 用any替代你的has函数
    你写的has xs x本质是判断x是否存在于xs中,这正好是高阶函数any的功能:any (==x) xs等价于has xs x。这里(==x)可以看成是隐式Lambda(也显式写成\y -> y == x),any会遍历列表,检查是否有元素满足这个谓词。

  2. 用foldr替代递归遍历
    foldr是Haskell中常用的列表折叠高阶函数,它从右往左遍历列表,用二元函数把元素和累积结果组合起来:

    • 初始累积值是[](空列表)
    • Lambda函数\x acc -> ...中,x是当前处理的元素,acc是已经处理完右侧所有元素得到的去重列表
    • 逻辑和你的递归版本完全一致:如果x不在acc里,就把x加到acc前面;否则直接保留acc

逻辑一致性验证

以输入[1,2,1]为例:

  • 你的递归版本会返回[2,1](保留最后一次出现的元素)
  • 高阶函数版本的计算过程:
    foldr f [] [1,2,1] = f 1 (f 2 (f 1 []))
    f 1 [] → 1 : [] → [1]
    f 2 [1] → 2 : [1] → [2,1]
    f 1 [2,1] → 1已存在,返回[2,1]
    最终结果:[2,1]
    

和递归版本的输出完全一致。

拓展:保留第一次出现的元素

如果需要保留列表中元素第一次出现的顺序(比如输入[1,2,1]返回[1,2]),可以用foldl配合反转:

uniqueFirst :: (Eq a) => [a] -> [a]
uniqueFirst = reverse . foldl (\acc x -> if not (any (==x) acc) then x : acc else acc) []

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 06:20:27