# Non-trivial functions that operate on any monad [closed]

I'm looking for examples of interesting methods that take an arbitrary monad and do something useful with it.

Monads are extremely general, so methods that operate on monads are widely applicable. On the other hand, methods I know of that can apply to any monad tend to be... really, really trivial. Barely worth extracting into a function.

Here's a really boring example: joinTwice. It just flattens an m m m t into an m t:

join n = n >>= id
joinTwice n = (join . join) n

main = print (joinTwice [[[1],[2, 3]], [[4]]])
-- prints [1,2,3,4]

The only non-trivial method for monads that I know of is bindFold (see my answer below). Are there more?

-

## closed as too broad by gnat, Bart van Ingen Schenau, GlenH7, Robert Harvey, ChrisF♦Nov 7 '13 at 22:46

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

Just to note, your bindFold is normally called sequence, and can be made generic over all Applicatives, not just Monads. The same goes for the more general version traverse. –  Ptharien's Flame Nov 1 '13 at 9:17
Control.Monad has many useful Monad utilities –  Thomas Eding Nov 1 '13 at 15:37
@Ptharien Thanks, that's useful to know. –  Strilanc Nov 1 '13 at 17:32

bindFold

bindFold turns a List m t into an m List t by folding bind across the list. It ends up being a different useful function for each monad.

Code

bindFold items =
item <- mitem
in foldl grow (return []) items

-- m=List: list all ways to choose one item from each sub-list
v1 = bindFold [[1,2,3], [4,5], [6]]
v2 = bindFold [[1,2,3], [4,5], [6], []]

-- m=Maybe: just all values or else nothing
v3 = bindFold [Just 1, Just 2, Just 3]
v4 = bindFold [Just 1, Just 2, Nothing]

-- m=IO: concatenates outputs
main = bindFold [print v1, print v2, print v3, print v4]

Output

[[1,4,6],[1,5,6],[2,4,6],[2,5,6],[3,4,6],[3,5,6]]
[]
Just [1,2,3]
Nothing

Uses

bindFold combines many useful functions into one:

• allWaysToChooseOneFromEach for List
• justAllOrNothing for Maybe
• printAll for IO
• whenAll for Future
• inSequence for Parser
• allOrError for Error
• chanceOfChoosingOneFromEach for ProbabilityDistribution
• etc
-