Reputation: 8412
The following function takes two lists returns all elements that occur in both lists at the same indices:
equal_els :: Eq a => [a] -> [a] -> [a]
equal_els xs ys = map fst $ filter (uncurry (==)) $ zip xs ys
Seeing how xs ys
occurs at the end on both sides, I did what I always do in that case: remove it! However, the resulting
equal_els = map fst $ filter (uncurry (==)) $ zip
does not compile anymore and I cannot for the life of me figure out what the error message is trying to tell me!
Couldn't match expected type ‘[a] -> [a] -> [a]’
with actual type ‘[b0]’
Relevant bindings include
equal_els :: [a] -> [a] -> [a] (bound at ...)
In the expression: map fst $ filter (uncurry (==)) $ zip
In an equation for ‘equal_els’:
equal_els = map fst $ filter (uncurry (==)) $ zip
Couldn't match expected type ‘[(b0, b0)]’
with actual type ‘[a0] -> [b1] -> [(a0, b1)]’
Probable cause: ‘zip’ is applied to too few arguments
In the second argument of ‘($)’, namely ‘zip’
In the second argument of ‘($)’, namely
‘filter (uncurry (==)) $ zip’
Upvotes: 2
Views: 170
Reputation: 33651
The type of $
is (a -> b) -> a -> b
, so it accepts a function and an argument, and then passes the argument to the function.
You are trying to pass zip
as a parameter, however, you should pass the result of zip
function, i.e. combine two functions. This is the purpose of .
(function composition):
Prelude> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
Prelude> let equal_els xs = map fst . filter (uncurry (==)) . zip xs
Prelude> equal_els [1, 2, 3] [1, 4, 3]
[1,3]
However, leaving the last element makes this function unreadable:
Prelude> let equal_els xs = map fst . filter (uncurry (==)) . zip xs
Prelude> let equal_els xs = (.) (map fst . filter (uncurry (==))) (zip xs)
Prelude> let equal_els xs = ((.) (map fst . filter (uncurry (==)))) . zip $ xs
Prelude> let equal_els = ((.) (map fst . filter (uncurry (==)))) . zip
So, I'd leave the function with one parameter.
Upvotes: 3