haskellfunctional-programmingmonadsoption-typemonadplus

Obtaining a Bool out of [Maybe Bool] which is guaranteed to contain at least one Just


I have an input list of type [Maybe SomeType] and a predicate p of type SomeType -> Bool, and I want to answer the question "Does the predicate p hold for all SomeTypes that happen to be in the input?".

The first part is easy: (map . fmap) p list is of type [Maybe Bool].

One important info is that I know that length list >= 1 and all isNothing list == False both hold, so there must be at least a Just True in (map . fmap) p list.

But how do I pull out one single Bool out of that list?

I thought that I could take advantage of folding (e.g. via foldl) and Maybe's MonadPlus instance, doing something like the following:

allTrueOrNothing :: [Maybe Bool] -> Bool
allTrueOrNothing = fromJust . foldl mplus mzero

but this is not quite true, because mplus returns the left operand if it's Just something regardless of what something is, so allTrueOrNothing will return True even if its input is [Just True, Just False].

What's the cleanest/most idiomatic way I can accomplish the task?

I see that I could simply filter out the Nothings and then and together the Justs, something like this:

allTrueOrNothing' :: [Maybe Bool] -> Bool
allTrueOrNothing' = all fromJust . filter (fmap not isNothing)

But I was more curious to know if there's a way to have those Maybe Bools behave like a Monoid aware of its Bool content.


Solution

  • The cleanest way is and . catMaybes.

    But you wanted to use Monoid that is aware of its Bool content, in the && kind of way. That's All:

    > foldMap (fmap All) [Just True,Nothing,Just False]
    Just (All {getAll = False})
    
    > foldMap (fmap All) [Just True,Nothing,Just True]
    Just (All {getAll = True})