user496579
user496579

Reputation: 23

Comparing elements in a list of pairs

I'm having trouble figuring this function out:

Define a function maybeA :: [(String, a)] -> Maybe (String, a, a) that takes a list of pairs. If the input list has two pairs (a1, b1), (a2, b2) such that a1 = a2, the function returns a tuple containing a1 and b1, b2. Otherwise it returns Nothing. Example: maybeA [("a", 1), ("b", 2), ("b", 3)] will return Just ("b", 2, 3).

Any hints?

Upvotes: 1

Views: 1793

Answers (2)

Yitz
Yitz

Reputation: 5117

Here is a "combinator approach" - breaking the problem into small, simple steps, and applying those steps one after the next using function composition:

import Data.List (sort, groupBy)
import Data.Maybe (listToMaybe)
import Data.Function (on)

maybeA = fmap formatAnswer . listToMaybe . dropWhile (null . drop 1) .
         groupBy ((==) `on` fst) . sort
  where
    formatAnswer ((a, b1):(_, b2):_) = (a, b1, b2)

Some notes:

  • fmap applies a function to the value inside a Maybe, if it exists. (fmap works in a similar way on many other types, too.)
  • (==)`on` fst tests whether two tuples are equal on their first elements.
  • sort compares both elements in a tuple, but it uses dictionary order. So it works here, but it sometimes changes the order of b1 and b2. If that is a problem for you, use sortBy (comparing fst) instead. sortBy is in the Data.List module, and comparing is in the Data.Function module.

Upvotes: 3

Sean Seefried
Sean Seefried

Reputation: 1279

If you're just looking for the first two occurrences where two pairs have the same first two elements then the following definition will work:

maybeA :: [(String, a)] -> Maybe (String, a, a)
maybeA = maybeA' []
  where
    maybeA' _ []           = Nothing
    maybeA' as ((x,y):xys) = 
      case lookup x as of
        Just y' -> Just (x,y,y')
        Nothing -> maybeA' ((x,y):as) xys

Note, that if you pass it a list containing (a1, b1), (a2, b2) and (a3, b3) where a1 == a2 and a2 == a3, it will only return Just (a1, b1,b2) not Just (a1, b1,b2,b3) (which wouldn't even be of the same type).

Designing a function which does this is left as an exercise :-)

Upvotes: 1

Related Questions