Udu
Udu

Reputation: 19

How to turn a list of tuples into a single list

I'm trying to turn a list of tuples into a single list with only the second value from each tuple.

targets :: [(a,b)] -> [a]
targets (x:xs) = [snd(x)] ++ targets xs

This is what I have so far but it is not working. Any help would be greatly appreciated.

Upvotes: 1

Views: 111

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

This is a mapping where for each 2-tuple, you take the second element, hence we can use map :: (a -> b) -> [a] -> [b]:

targets :: [(a,b)] -> [b]
targets = map snd

Notice that the return type is [b]: a list of bs, not as. Your type for a Graph however has as type [(Node a, [Int])], so you will need to concatenate these lists together.

Upvotes: 1

Aplet123
Aplet123

Reputation: 35482

There are two mistakes in your code. The first of which, GHC will warn you about:

<interactive>:3:30: error:
    • Couldn't match type ‘a’ with ‘b’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          targets :: forall a b. [(a, b)] -> [a]
        at <interactive>:2:1-25
      ‘b’ is a rigid type variable bound by
        the type signature for:
          targets :: forall a b. [(a, b)] -> [a]
        at <interactive>:2:1-25
      Expected type: [b]
        Actual type: [a]

The second element of the tuple is of type b (since you declare the tuple to be (a, b)), so the resulting array should not be [a] (what GHC calls the actual type), but it should be [b] (what GHC calls the expected type). Then, you're also missing a case. What if it's called on the empty array? Then it won't match (x:xs), so you should add a special case for that (also remember that every recursive function should have a base case):

targets :: [(a, b)] -> [b]
-- using x:y instead of [x] ++ y since they do the same thing
targets (x:xs) = snd x:targets xs
-- the base case for when nothing matches
targets _ = []

Upvotes: 1

Related Questions