f :: Int -> Either String Int
f 0 = Left "Zero is not allowed!"
f x = x + 42
g :: Int -> [Int]
g x | x > 1 = [1..x]
Then, in a dynamically typed language, nothing stops you from writing something like:
f =<< g 42
Anyway, this means you don't have a monad -- you just have a function that calls other functions. It's a fine way to reuse code, but it's not a monad.
Having also implemented a monad library in a dynamically-typed language, I am well aware of what happens when one operand of bind returns the wrong type. The rest of the computation silently proceeds with that type, until it happens to change again. This results in a subtle loss of information, rather than outright failure.
Like I said, programming with combinators is a great way to reuse code -- but not all combinators that are of type "f a -> (a -> g b) -> g b" are monadic. It's only a monad when f = g.
For example, I see you are a Perl hacker. In Perl, even my simple (42 + "foo") example results in "subtle loss of information." This doesn't mean that + doesn't work in Perl, just that someone other than the compiler has to make sure the values on either side have compatible types.
Look at the clojure.contrib.monad documentation, and you'll see that monads do have benefits beyond "normal" combinators, even if those benefits don't include all the static safety of Haskell or ML. You get the "domonad" macro which provides the same benefits as Haskell's "do" syntactic sugar. You get generic lifting/mapping/chaining functions that you can use with any monad (like the Control.Monad module in Haskell), and you can write similar generic functions of your own:
Sure, but I don't call "+" addition, it's just Perl's "plus operator" which happens to be defined over numbers and strings.
Personally, I don't see why every language is trying to copy Haskell's monads. A monad is not some deeply important concept, it's just an abstraction that happened to be very useful in the context of Haskell's type system. Without Haskell's type system, it is not quite as useful, and it's possible that other abstractions would be better.
Sure! I'd be happy to agree with this statement.
Functors and pointed functors and arrows are also quite important.
 Though not the most important one.
Sorry to be a pedant, but dynamically typed is not the same as without a type system, it is merely without a type checker. They probably look the same to somebody well versed in Haskell but the distinction matters.
With a dynamic type system you get your errors at least at runtime. With no type system your program just behaves wrong.
I add: They aren't enforced completely in Haskell, either.
(And you can't even express every monad in Haskell. E.g. you can't even make Set a functor in Haskell.)
Well sure, because map on a set is only defined over functions that return values that can be compared for equality, whereas the generic functor map is defined over all functions.
 I hope I got the names correct.
This surrounding context inference feature, which is useful for type classes other than monads, has the unusual consequence that you need to specify more typeinfo in a dynamic language.
Unlike haskell which can choose an implementation based on the return type of return and bind, you do have to spell it out. The macro with-monad will wrap a set of expressions up in the correct monad, and the domonad monad comprehension form is also able to accept an optional monad name (useful if you aren't inside a with-monad form, or if you need a different monad)