In practice, most of the monads I've worked with behave like some kind of implicit context.
It's like when you and a friend are trying to have a conversation about a mutual friend. Every time you say "Bob," you're both referring to the same Bob, and that fact is just implicitly threaded through your conversation due to the context of Bob being your mutual friend.
You can, of course, have a conversation with your boss (not your friend) about your skip-level manager (not your friend) who happens to be named Bob. Here you can have another conversation, again with some implied connotation that only makes sense within the context of the conversation. You can even utter the exact same words as you did with your friend, but they will carry a different meaning because of the different context.
In programming it's the same. The way that tell
behaves depends on which monad you're in; the way that information is assembled (>>=
) depends on which monad you're in. Same idea, different mode of conversation.
Heck, even the rules of the conversation can be monadic. "Don't tell anyone what I told you" hides information the same way that runST
prevents references from escaping the ST
monad. Obviously, conversations can have layers and layers of context, just like we have stacks of monad transformers.
Hope that helps.