Can you explain the nondeterminism part of your comment more?
A nice demonstration of this is writing a very simple regex matcher with the List monad. A naive implementation in Haskell with the List monad Just Works, because it's effectively a direct translation of Nondeterministic Finite Automata into code.
δ : Q × E ⟶ Q
δ : Q × E ⟶ P(Q)
... where Q denotes the set of the automaton's states, E its alphabet of input symbols, and P the power set operation. Deterministic automata arrive at a definite, single state drawn from Q, while non-deterministic automata may arrive at a set (~list) of possible states, when given a current state from Q and next input symbol from E.[0] https://en.wikipedia.org/wiki/Deterministic_finite_automaton
[1] https://en.wikipedia.org/wiki/Nondeterministic_finite_automa...
Non-determinism, in that given some set of inputs it's possible to receive a collection (a list) of possible outputs.
With lists you can express things like all possible pairings of all possible outcomes, or the Cartesian product:
ghci> liftM2 (,) ['a', 'b', 'c'] [1,2,3]
[('a',1),('a',2),('a',3),('b',1),('b',2),('b',3),('c',1),('c',2),('c',3)]
... or in more explicit monadic do-notation: ghci> :{
ghci| do
ghci| x <- ['a', 'b', 'c']
ghci| y <- [1,2,3]
ghci| return (x, y)
ghci| :}
[('a',1),('a',2),('a',3),('b',1),('b',2),('b',3),('c',1),('c',2),('c',3)]
and so on.