user12174294
user12174294

Reputation:

Checking if a given Integer is the first element of a tuple in a list of tuples

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

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

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

shree.pat18
shree.pat18

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

Related Questions