Haskell中用递归与模式匹配实现连续重复列表元素去重
unrepeat Function for Consecutive Duplicates Let's start by breaking down what's not working with your current code. Right now, your implementation uses a list comprehension that filters out all occurrences of x from the recursive call result—not just the consecutive duplicates. That means if you ran unrepeat [1,1,2,1], you'd get [1,2] instead of the expected [1,2,1]—the non-consecutive 1 gets incorrectly removed too.
The Correct Recursive Approach with Pattern Matching
We need to focus only on adjacent, consecutive duplicates. Here's how to structure the recursion properly by checking adjacent elements directly in the pattern matches:
unrepeat :: Eq a => [a] -> [a] -- Base case: empty list stays empty unrepeat [] = [] -- Base case: single element list stays unchanged unrepeat [x] = [x] -- Handle cases with at least two elements unrepeat (x:y:xs) | x == y = unrepeat (y:xs) -- Skip x (it's a consecutive duplicate), keep processing the rest | otherwise = x : unrepeat (y:xs) -- Keep x, then process the rest starting with y
How This Works (Walkthrough of Your Examples)
Let’s verify with your sample inputs to see the logic in action:
For
unrepeat [True,True,True,True]:- Start with
True:True:[True,True]→ x and y are equal, so callunrepeat (True:[True,True]) - Next,
True:True:[True]→ again equal, callunrepeat (True:[True]) - Then
True:True:[]→ equal, callunrepeat [True] - Single element returns
[True]→ final result is[True]
- Start with
For
unrepeat [1,1,2,1,3,3,3]:1:1:[2,1,3,3,3]→ equal, callunrepeat (1:[2,1,3,3,3])1:2:[1,3,3,3]→ not equal, so1 : unrepeat (2:[1,3,3,3])2:1:[3,3,3]→ not equal, so2 : unrepeat (1:[3,3,3])1:3:[3,3]→ not equal, so1 : unrepeat (3:[3,3])3:3:[3]→ equal, callunrepeat (3:[3])3:3:[]→ equal, callunrepeat [3]- Single element returns
[3]→ building back up gives[1,2,1,3]
Why Your Original Code Failed
Your line x : [ k | k <- unrepeat(xs), k /=x] was removing every instance of x from the rest of the list, not just consecutive ones. For example, in [1,1,2,1], after processing the first 1, it would filter out the final 1 from the recursive result of unrepeat [1,2,1], leading to an incorrect output.
内容的提问来源于stack exchange,提问作者Coding Elf

