Reputation: 331
I have code like this:
appd (a:e) ((c,b):bs) | a == c && bs /= [] = b:appd(a:e) bs
| a /= c && bs /= [] = appd (a:e) bs
| a /= c && bs == [] = appd e ((c,b):bs)
| otherwise = b:appd e ((c,b):bs)
It loops throught two lists like [1,2,3]
and [(1,2),(6,5),(3,5)]
and takes first element of first list and compares it to first element of each tuple in other list, if they are equal then save second element of this tuple. It works fine, but comparison does not work if I take second element of first list, in this case 2
.
For example if I have lists like [1,2,3]
and [(1,2),(6,5),(3,5)]
, then function takes 1
from first list and compares to 1
, then to 6
, then to 3
, that works but it does not take second element of first list - 2
and does not do the comparison again. Whats wrong?
Upvotes: 0
Views: 131
Reputation: 38247
First of all, let me note that you should have included the error message you were getting. You should also have shown us some sample output and sample input.
Anyway: your current appd
doesn't handle empty lists, so you need to start by adding cases for that:
appd _ [] = []
appd [] bs = snd <$> bs -- you can decide to use [] instead
appd (a:e) ((c,b):bs)
| a == c && bs /= [] = b:appd(a:e) bs
| a /= c && bs /= [] = appd (a:e) bs
| a /= c && bs == [] = appd e ((c,b):bs)
| otherwise = b:appd e ((c,b):bs)
now your function works on the input you've provided, but I'm not sure it returns the results you desire:
*Main> appd [1,2,3] [(1,2),(6,5),(3,5)]
[2,5,5]
Furthermore, I've cleaned up your code a little bit and annotated your function with an explicit type signature:
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd [] bs = snd <$> bs
appd _ [] = []
appd as@(a:ass) bs@((c,b):bss)
| a == c && bss /= [] = b : appd as bss
| a /= c && bss /= [] = appd as bss
| a /= c && bss == [] = appd ass bs
| otherwise = b : appd ass bs
Also, you can use a much simpler, non-recursive implementation to get the same results as above:
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as bs = snd <$> filter (\(a,_) -> a `elem` as) bs
or if you like point free (a.k.a. tacit):
appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as = (snd <$>) . filter ((`elem` as) . fst)
Note: <$>
is an alias for fmap
, which in turn behaves exactly like map
when used on lists.
Upvotes: 1