What does it mean to "run" inside a monad?
Authors who write books and articles often use metaphors and less precise language when they try to explain concepts. The purpose is to give the reader a conceptual intuition for what's going on.
I believe that the concept of 'running' a function falls into this category. Apart from IO
, you're right that the functions you use to compose, say, []
, Maybe
, and so on are no special from other functions.
The notion of running something inside of a monad comes, I think, from the observation that functors are containers. This observation applies to monads as well, since all monads are functors. [Bool]
is a container of Boolean values, Maybe Int
is a container of (zero or one) numbers. You can even think of the reader functor r -> a
as a container of a
values, because you can imagine that it's just a very big lookup table.
Being able to 'run a function inside a container' is useful because not all containers enable access to their contents. Again, IO
is the prime example, since it's an opaque container.
A frequently asked question is: How to return a pure value from a impure method. Likewise, many beginners ask: How do I get the value of a Maybe
? You could even ask: How do I get the value out of a list? Generalised, the question becomes: How to get the value out of the monad.
The answer is that you don't. You 'run the function inside the container', or, as I like to put it, you inject the behaviour into the monad. You never leave the container, but rather let your functions execute within the context of it. Particularly when it comes to IO
, this is the only way you can interact with that container, because it's otherwise opaque (I'm here pretending that unsafePerformIO
doesn't exist).
Keep in mind when it comes to the bind method (>>=
) that while the function 'running inside of it' has the type a -> m b
, you can also 'run' a 'normal' function a -> b
inside the monad with fmap
, because all Monad
instances are also Functor
instances.