There's a fundamental difference, but it's a little subtle.
The key notion of Monads is this nesting thing. It's sequential, but what it is really expressing is *dependency*. That is, you have to compute a value of A first; once you have that, you can compute B. Once you have a value of B, you can compute C.
In that respect, it's actually quite different from A && B && C, because those values are *independent* -- the value of A doesn't affect the value of B. Intuitively, I think && is an applicative operator, but I'm not sure whether it follows all of the relevant rules. Roughly speaking, Applicative means "compute the elements independently, then combine their values into this type".
Yes, you're combining values in &&, but the value of B itself doesn't depend on the value of A. If you look at the Monad examples above, in each of them we're computing the "inner" values based on the "outer" ones. (Well, mostly -- the Future example actually shows one where you *could* do the operations in parallel; it's arguably a bug, or at least an inefficiency, that we're doing them strictly in order. Scala just happens to make it easier syntactically to do it this way.)
Really, I should have described this as dependent vs. independent in the first place (I often do), but that didn't occur to me when I was writing this up...
no subject
The key notion of Monads is this nesting thing. It's sequential, but what it is really expressing is *dependency*. That is, you have to compute a value of A first; once you have that, you can compute B. Once you have a value of B, you can compute C.
In that respect, it's actually quite different from A && B && C, because those values are *independent* -- the value of A doesn't affect the value of B. Intuitively, I think && is an applicative operator, but I'm not sure whether it follows all of the relevant rules. Roughly speaking, Applicative means "compute the elements independently, then combine their values into this type".
Yes, you're combining values in &&, but the value of B itself doesn't depend on the value of A. If you look at the Monad examples above, in each of them we're computing the "inner" values based on the "outer" ones. (Well, mostly -- the Future example actually shows one where you *could* do the operations in parallel; it's arguably a bug, or at least an inefficiency, that we're doing them strictly in order. Scala just happens to make it easier syntactically to do it this way.)
Really, I should have described this as dependent vs. independent in the first place (I often do), but that didn't occur to me when I was writing this up...