Reputation: 1173
I just started learning Haskell (I'm trying to make a mastermind solver).
I have to count how many times one color from a lists occurs in another list:
reaction [Green, Purple, Green, Green] [Purple, Green, Blue, Yellow] 0
Would have to give me the result "2", Because "Green" from list 1 occurs 1 time in list 2, and the same goes for "Purple". So I've written a little piece of code:
reaction [] ys n = n
reaction (x:xs) ys n = foldr (\y _ -> if x == y then reaction (filter' x xs) ys n + 1 else reaction xs ys n + 0) n ys
filter' c xs = filter(\x -> x /= c) xs
It takes the head X from list 1 and compares it to every element in list 2, if it is the same it will filter all the values from list 1 which are corresponding to X (so it won't count any duplicates) and add + 1 to "N". However it gives me the result "1", and I really can't seem to find out why... I hope anyone can help me! Steven
Upvotes: 1
Views: 1150
Reputation: 66404
In your code, you throw away the second argument (the accumulator) of the function that you pass to foldr
:
foldr (\y _ -> ...
I can't think of a use case of foldr
where you would want to do that.
Your question seems to stem from a misunderstanding of foldr
. Are you sure you understand what this function does? If you have any doubt, read, for instance, this section of the Wikipedia page on folds; you should find the diagram explaining what a right fold is particularly illuminating.
If I correctly understand what you want to do, the following approach should do the job:
import Data.List
data Color = Blue | Green | Purple | Yellow
deriving Eq
reaction :: Eq a => [a] -> [a] -> Int -> Int
reaction xs ys n = foldr (\x acc -> length (filter (== x) ys) + acc) n $ nub xs
For information, the nub
function takes a list and returns a list formed by removing all duplicates element from it; it is exported by the Data.List
module.
λ> reaction [Green, Purple, Green, Green] [Purple, Green, Blue, Yellow] 0
2
Upvotes: 1
Reputation: 21811
First, filter'
is just filter (/= x)
.
From your description of the problem, a clearer way to write this (at least initially) is
reaction [] ys n = n
reaction (x : xs) ys n | x `elem` ys = reaction (filter (/= x) xs) ys (n+1)
| otherwise = reaction xs ys n
This doesn't appear to be a simple fold to me because the list you are iterating over (xs
) changes as you iterate over it.
Upvotes: 1