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) []
逐行解释
用
any替代你的has函数
你写的has xs x本质是判断x是否存在于xs中,这正好是高阶函数any的功能:any (==x) xs等价于has xs x。这里(==x)可以看成是隐式Lambda(也显式写成\y -> y == x),any会遍历列表,检查是否有元素满足这个谓词。用
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
相关产品推荐
相关产品推荐

