As are parsers, uniqueness, randomness, non-determinism, readers, writers, regions, resource management, local-state threads (ST monad), probability distributions, software transactional memory, ....
Another nice thing is composing various monads to build a custom one for the purpose you need.
For example:
StateT S1 (EitherT Err (State S2)) a
Will be a stateful computation that always has yields a new S2 value, even in exceptions (preserving any modifications up to the exception) but only yields an S1 in the case of success.This is just one of infinite possible compositions of monad transformers.
If you hard-code a certain ambient monad into your language, you won't be able to use monads as a DSL for the use case you have at a certain time.
For example, in the application I'm developing now, I use a "Transaction" monad that guarantees that my key/value store transactions cannot do any IO or anything other than read keys and write keys. As a bonus, that means I don't even need transactionality from the underlying data store -- I can "revert" or "commit" by implementing the Transaction monad as a state tracker of all the changes on top of a hidden IO layer that exclusively allows reading keys.
This also means I can implement useful transactional primitives such as "forkScratch" which allows me to fork the transactional state, run an action in that forked state, discard its transactional side effects, and keep its result. I use this to "try out" a transaction, see if it would work (in my context, type-check the new state and discard it) without actually having any effect.
tl;dr: There isn't a finite set of useful monads you can bake into the language. There are infinite compositions of useful monads.