In addition, I want to note that monads are not "mystical". Especially container-like monads (list, Maybe, Identity) are pretty clear. They are similar to functors, but with a twist: using fmap , the "form" (for example, the number of elements in the list) of the original functor is saved, for example. you cannot use fmap to implement something like filter . Therefore, monads have a "bind" function (in Haskell it (>>=) ) that allows for such things, but they are also not magical (for example, for lists, this is the same as the good old concatMap ). In addition, monads have a return function to wrap a single value.
Now, many other things, not "container-like" things, are monads. There are monads that can work with "stored computing" ( Cont to continue the monad). They can provide ( Reader ), collect ( Writer ) or hold ( State ) some kind of "additional context". A very useful “context” is the “state of the rest of the world”, better known as IO . In this case, the type system (especially the restrictions imposed by polymorphism and class types) can protect against unwanted interactions and force a certain order of calculations (which is not trivial in a lazy language), so we do not need dirty hacks or a language to do IO in a pure language . Some people think that this is a kind of magic, but this is just a clever use of the type system, and monads are not the only solution to this problem (for example, the Clean language uses types of uniqueness for this).
source share