Reputation: 23
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 returnJust ("b", 2, 3)
.
Any hints?
Upvotes: 1
Views: 1793
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
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