Reputation:
I have an assignment in which I need to check if a given Int is the first element of any tuple in a list of tuples. For example, if I want to check if 1
is the first element of any tuple on the list [(2,3), (3,3), (2,7)]
it should return False
, however, if I want to check if 1
is the first element on the list [(2,2), (1,2), (3,4)]
, it should return True
.
This is my attempt:
isFirst :: (Eq a) => a -> [(a,b)] -> Bool
isFirst _ [] = False
isFirst x [(y1, y2)] = x == y1
isFirst x ((y1, y2):l) = if y1 : isFirst l then True
else False
I'm still new to Haskell so I really have no clue if I'm even close to the right solution, Thanks for your help!
Upvotes: 2
Views: 614
Reputation: 476584
We can make use of any :: Foldable f => (a -> Bool) -> f a -> Bool
here to check if any of the 2-tuples has a first element that is equal to the one we are looking for:
isFirst :: Eq a => a -> [(a,b)] -> Bool
isFirst x ys = any (\(y, _) -> x == y) ys
or shorter:
isFirst :: Eq a => a -> [(a,b)] -> Bool
isFirst x = any ((==) x . fst)
Upvotes: 2
Reputation: 21757
Here's how you can modify the function:
isFirst :: (Eq a) => a -> [(a,b)] -> Bool
isFirst _ [] = False
isFirst x [(y1, y2)] = x == y1
isFirst x ((y1, y2):l) = (x == y1) || isFirst x l
What was wrong with the earlier implementation?
Writing y1 : isFirst l
means you want to add y
to the start of the list generated by isFirst l
. But isFirst
should return a Bool
, so that wouldn't work.
What's the fix?
Explicitly check for the first tuple, and then recursively call isFirst
on the rest of the list. Joining the two checks with an OR will be a logically correct operation, since each check returns a Bool
result.
Upvotes: 2