Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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?

share|improve this question

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.

1  
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
1  
@Ptharien Thanks, that's useful to know. –  Strilanc Nov 1 '13 at 17:32

1 Answer 1

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 =
    let grow mhead mitem = do head <- mhead
                              item <- mitem
                              return (head++[item])
    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
share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.