I'm attempting to be strongly consistent in everything I'm saying, but it's not necessarily possible to both do that and keep speaking simply.
The why of monads is that they're a very nice API or Interface that allows you to write easily analyzed and easily refactored programs. Most of the other descriptions are the why of a particular type which happens to instantiate the API.
Indeed, it's arguably not even the right question. "When is something monadic?" is a better one; "monad" is an adjective, not a noun. In Java terms, "Monad" is an interface and something is "monadic" if it implements the interface. (Except Java's type system can not express "Monad", so that doesn't work as a concrete example, but the idea is there.)
I'm sure you've seen me claim this on /r/haskell, where I think people operate in a context where they find this so obvious that the very idea that there could be a problem is confusing... this is the sort of context that leads me to that claim, though. Regardless of whether it's a noun in math, in programming it's an adjective.
As I said, Python decorators are essentially just a syntax for function composition.
@deco
def g(args): g := deco(g(args): body)
body
where (g := a) means a is assigned to the name g. As it turns out, functions form a type which is a functor over the result type. The fmap (arrow map) is just function composition. In Haskell you would write this as instance Functor ((->) r) where
fmap g f = g . f
where the (.) syntax is also function composition, very similar to the @deco syntax in Python. In this sense, I stated that @deco is a Functor.Now, the function data type also admits a Monad instance (which some people abuse terminology to say "functions are monads" but I highly dislike that terminology when speaking carefully).
instance Monad ((->) r) where
return a = \_ -> a
(f >>= g) x = g (f x) x
So in this way, the function type instantiates both Functor and Monad, but composition (which is (.) in Haskell and @deco is Python) is not directly related to the Monad.Instead, a function's Monad instance allows us to "defer application" and translate something like
\x -> (1 + x, 2 + x)
into do a <- (1+)
b <- (2+)
return (a, b)
In this format it's pretty stupid looking, but we also tend to call this monad instance the "Reader Monad" which indicates computations which occur under a fixed set of configuration information—some static global variables.For instance, if I had a Key type which represented some encryption key I could change my encrypt and decrypt functions from
encrypt :: Key -> String -> String
decrypt :: Key -> String -> String
to encrypt :: String -> Reader Key String
decrypt :: String -> Reader Key String
which, allows us to defer that extra `Key` argument until later.So, that's what I meant by saying that @deco isn't the Monad that its Functor represents—it only has the composition aspect, not the deferred application aspect.
Also, you wrote:
> decoration [...] forms a [...] functor. That [...] Functor also provides a monad
That is entirely at odds with the statement:
> Decorators do not provide a monad at all
Frankly, at this point i'm strongly considering the possibility that you're just trolling me.