Haskell函数式编程练习:生成含过滤列表与计数的元组
Hey there! Sounds like you’ve already got a grip on the core logic here—great start! Let’s break down how to wrap that logic into the required tuple output, step by step.
First, let’s clarify the function’s requirements clearly:
- It takes an element
zand a list[a](whereais any type that can be compared for equality, hence theEq aconstraint) - It returns a tuple: the first element is the list with all
zremoved, the second is the number of timeszappeared in the original list
Option 1: Recursive Implementation (Easy to Follow)
Recursion is straightforward for list processing in Haskell. We’ll handle the base case (empty list) first, then build up the result for non-empty lists:
removeAndCount :: Eq a => a -> [a] -> ([a], Int) -- Base case: empty list has no elements to remove, count is 0 removeAndCount _ [] = ([], 0) -- Recursive case: check if current element matches z removeAndCount z (x:xs) | x == z = let (restOfList, count) = removeAndCount z xs in (restOfList, count + 1) -- Skip x, increment count | otherwise = let (restOfList, count) = removeAndCount z xs in (x:restOfList, count) -- Keep x, count stays same
Option 2: Foldr Implementation (More Idiomatic Haskell)
For a more concise, idiomatic approach, we can use foldr to accumulate both the filtered list and the count in one pass. This avoids explicit recursion and is often preferred in Haskell for list transformations:
removeAndCount :: Eq a => a -> [a] -> ([a], Int) removeAndCount z = foldr updateResult ([], 0) where updateResult x (accList, accCount) | x == z = (accList, accCount + 1) | otherwise = (x:accList, accCount)
Testing the Output
Let’s test with your example input to see how the tuple output works:
Input:
removeAndCount 2 [2,3,4,2,5]
Output:([3,4,5], 2)
If you’re working in GHCi, just call print $ removeAndCount 2 [2,3,4,2,5] to see the tuple printed directly—Haskell handles the tuple formatting automatically, so you don’t need to do any extra work to structure the output as long as you return the tuple correctly.
Key Note: The Eq a Constraint
Don’t forget the Eq a type constraint! Since we need to check if elements are equal to z, the type a must support equality comparisons. Without this constraint, the compiler will throw an error.
内容的提问来源于stack exchange,提问作者Frank Ponte

