complexFn = do
x <- getSomeData
y <- computeWith x
z <- computeSomeMore y
return z
Let's say you have here straightforward imperative code. Of course, a real example would be more complex. But suppose x is now a list and you want to vectorise computeWith. Put your x in a box/monad, let's call it Parallel. Define return and bind to be parallel (bind = par . fmap, or something), and that's it. Transparent parallelism.
Maybe it does numerical algorithms, and you want x to be an interval, or a tuple (value, error). Again, define the corresponding monad. Same thing with non-deterministic computation, amb-like operators, passing state between calls... The code that calls them stays the same.
It also provides type safety for operations. For instance, some Haskell libraries allow programmers to specify a network protocol with monads, then write servers/clients that are statically checked to be correct. All sorts of things like that.
Conceptually, a monad is a box with a tag on it (the name of the monad), and your rules for (1) putting things into it, and (2) applying functions to what's inside. Plus compile-time guarantees that you can't do weird things with them, like mix tags and stuff.
Let's say you have here straightforward imperative code. Of course, a real example would be more complex. But suppose x is now a list and you want to vectorise computeWith. Put your x in a box/monad, let's call it Parallel. Define return and bind to be parallel (bind = par . fmap, or something), and that's it. Transparent parallelism.
Maybe it does numerical algorithms, and you want x to be an interval, or a tuple (value, error). Again, define the corresponding monad. Same thing with non-deterministic computation, amb-like operators, passing state between calls... The code that calls them stays the same.
It also provides type safety for operations. For instance, some Haskell libraries allow programmers to specify a network protocol with monads, then write servers/clients that are statically checked to be correct. All sorts of things like that.
Conceptually, a monad is a box with a tag on it (the name of the monad), and your rules for (1) putting things into it, and (2) applying functions to what's inside. Plus compile-time guarantees that you can't do weird things with them, like mix tags and stuff.