Reputation: 53
I'm just starting to use Haskell, and I'm having what most of you reading would probably consider a beginner blunder.
Consider a list of tuples myTupleList = [(3,6),(4,8),(1,3)]
Nice. I wrote this function to return the list of tuples in which the second element in the first tuple, is double the first element: (Ex using myTupleList: double myTupleList , which returns [(3,6),(4,8)] )
double [] = []
double (x:xs)
|(snd x) == 2 * (fst x) = x: double xs
|otherwise = double xs
Now I'm sure this isn't the prettiest function in the world, but it works. The problem now is adapting it to use filter. This is my current attempt:
double [] = []
double xs = filter ((2 * (fst(head xs))) == (snd(head xs))) xs
To my undestanding, filter recieves two arguments: a boolean expression and a list. However, I'm getting the following error:
Couldn't match expected type ‘(a, a) -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the first argument of ‘filter’, namely
‘((2 * (fst (head xs))) == (snd (head xs)))’
In the expression:
filter ((2 * (fst (head xs))) == (snd (head xs))) xs
In an equation for ‘double’:
double xs = filter ((2 * (fst (head xs))) == (snd (head xs))) xs
• Relevant bindings include
xs :: [(a, a)] (bound at Line 9, Column 8)
double :: [(a, a)] -> [(a, a)] (bound at Line 8, Column 1)
I'm sure this is just some silly error or limitation of Haskell as a functional language that I'm not accustomed to or understanding properly, but it would be great to get some help with this.
Thanks
Upvotes: 5
Views: 85
Reputation: 476699
filter
expects a function a -> Bool
, but (2 * (fst(head xs))) == (snd(head xs))
is not a function that maps an element to a Bool
, but simply a Bool
. It does not make much sense here to use head x
, you use the parameter to get "access" to the element:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double xs = filter (\x -> 2 * fst x == snd x) xs
You can use pattern matching to unpack the 2-tuple and thus no longer need fst
and snd
. Furthermore you can perform an η-reduction, and thus remove xs
both in the head and the body of double
in this case:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (\(a, b) -> 2 * a == b)
This gives us:
Prelude> double [(3,6),(4,8),(1,3)]
[(3,6),(4,8)]
We can even make the predicate point-free:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (uncurry ((==) . (2 *)))
Upvotes: 5