Benjamin Maurer
Benjamin Maurer

Reputation: 3753

Mapping and filtering a list of maybes with a maybe returning function

I have a list of maybes and a function that gives me a node's color (if present):

maybeNeighbors :: [Maybe Node]
nodeColor      :: Node -> Maybe Color

Now I'd like to map colors to nodes, and as intermediate step I want to have a list of tuples:

coloredList    :: [(Color, [Node])]

(Because I'll construct a Map from it later with listToUFM_C (++) listColored)

Here is what I have so far, it works but seems ugly:

listColored    =  mapMaybe (\n -> nodeColor n >>= \c -> Just (c, [n])) $ catMaybes maybeNeighbors

(using catMaybes and mapMaybe from Data.Maybe)

I feel like I'm missing something, that I should be able to do something like (fmap . fmap) func maybeNeighbors, but I can't figure out how func should look like. Or a function like this, which I can't find either: (Maybe a -> Maybe b) -> [Maybe a] -> [Maybe b]

Edit:

I'm working on a graph coloring problem and I want a list of nodes that have the same color. Here is an example to test in GHCi:

let l = [Just (1, Just 'a'), Just (2, Just 'a'), Nothing, Just (3, Just 'b'), Just (4, Nothing)]

Upvotes: 2

Views: 798

Answers (2)

sshine
sshine

Reputation: 16115

If I understand correctly, you're making a function [Maybe Node] -> Map Color [Node]?

colorMap :: [Maybe Node] -> Map Color [Node]
colorMap = Map.fromListWith (++) . listColored

listColored :: [Maybe Node] -> [(Color, [Node])]
listColored = mapMaybe $ \maybeNode -> do
  node <- maybeNode
  color <- nodeColor node
  pure (color, [node])

Edit: Isolating the listColored part for better comparison with Fyodor's list comprehension.

Upvotes: 1

Fyodor Soikin
Fyodor Soikin

Reputation: 80754

This seems like it would be expressed the cleanest as a list comprehension:

listColored = 
    [ (c, [n])
    | Just n <- maybeNeighbors
    , Just c <- [nodeColor n]
    ]

Inside a list comprehension, a pattern-match failure will result in just skipping the element, so you'll naturally get rid of Nothings in maybeNeighbors as well as Nothing outputs from nodeColor.

Upvotes: 4

Related Questions