3 ms·
In C++ terms, I like to explain it like this. By analogy, consider classes that overload the "+" and "*" (etc.) operators and call them "arithmetic" classes, s
by throwaway81523 5y ago
In C++ terms, I like to explain it like this. By analogy, consider classes that overload the "+" and "*" (etc.) operators and call them "arithmetic" classes, so you can have them for regular numbers, complex numbers, matrices, etc. They tell the compiler to take an expression like "a+b" and convert it to a function call "someclass.add(a,b)" where someclass is determined from the types of a and b (let's say they both have to be the same type).
Ok, now consider a compound statement like { x; y; }. If there are more than two statements inside the braces, think of that as nested two-statement versions: {x; {y; z;} }. Please stretch your definition of C++ slightly so that statements are expressions, e.g. {x; y;} is an expression.
A "monadic" class in this scenario is a class that overloads the semicolon in compound statements. It expects the class members to have a method called "bind", so {x; y;} becomes "bind(x, [](a) { y })" (that is supposed to be a C++ lambda in the 2nd arg). The bind method receives the value from x and a lambda that it can choose to run this value through.
If the bind method simply takes the value of x and feeds it to the lambda, then it basically just runs x and y in sequence. The callback style should remind you of node.js if you are familiar with that. The obvious thing happens if you nest a bunch of these. This is how Haskell's I/O monad works: it just does the expressions in sequence. Rather than a compound statement with curly braces, Haskell uses a "do" block, but it's the same idea.
And, the idea also generalizes: instead of doing the expressions in sequence, it could spin off separate threads for each one and do them simultaneously (Haskell's Parallel monad), it could run some action over all the elements of a list (the List monad), etc.
Monads basically package the node.js control inversion and nested lambda cruft into a design pattern that lets you write what looks like straightforward sequential code, and also generalizes what it can do.
They are a traditional stumbling block in Haskell because several parts of Haskell interact to make them work: the semantics (described above), the type system (omitted here), and the implementations of specific monads (I gave a few examples like IO, Parallel, and List, but there are more). So you have to examine a few existing monads and understand how they are used, before the whole idea really makes sense. There is a good document called the "Typeclassopedia" that gives more examples.
I hope this helps!