EatRocks
EatRocks

Reputation: 31

How do you sum the individual elements of a pair in a list?

Im trying to take the first and second element of the pair from a list so they can be summed. Here is my code, I am not sure why it is giving an error

func :: [(Double,Double)] -> (Double,Double)
func [(x, y)] = map fst (x,y)

Upvotes: 2

Views: 1604

Answers (1)

bradrn
bradrn

Reputation: 8477

First, let's take your current, non-working definition:

func :: [(Double,Double)] -> (Double,Double)
func [(x, y)] = map fst (x,y)

This has several things wrong with it:

  • Your pattern match [(x, y)] only matches a list with exactly one element. Any list with 2 or more elements will cause an error since they do not match.
  • map cannot be applied to tuples; it can only be applied to lists.
  • Even if you could map over a tuple, fst must be applied to a tuple directly - fst (a, b) gives a, while map fst (a, b) doesn't make sense.

Let's look at some alternate definitions.

List comprehension

func_1 :: [(Double,Double)] -> (Double,Double)
func_1 list =
    let fsts = [ a | (a, _) <- list ]
        snds = [ b | (_, b) <- list ]
    in (sum fsts, sum snds)

This separately extracts each first element from the list, then each second element from the list, then adds them together.

Mapping

func_2 :: [(Double,Double)] -> (Double,Double)
func_2 list =
    let fsts = map fst list
        snds = map snd list
    in (sum fsts, sum snds)

Maps fst over each element of the input list to get a list of all first elements of the list. Then maps snd to do the same for second elements.

Recursion

func_3 :: [(Double,Double)] -> (Double,Double)
func_3 [] = (0, 0)
func_3 ((a,b) : xs) =
    let (a', b') = func_3 xs
    in (a+a', b+b')

A bit of a different approach. Lists in Haskell are formed recursively: [a, b, c] is equivalent to (a : (b : (c : []))). This means we can use pattern matching to get the first element of the list as well as all the other elements of the list. This definition works in two parts:

  • If the list has no elements, just return (0, 0) (the base case).
  • If the list has at least one element, take the rest of the list (e.g. [b, c] if [a, b, c] was given, or [] if [a] was given), calculate its sum using func_3 again, then add the first element back on.

Upvotes: 7

Related Questions