Why is the bind operator (>>=) defined as it is?

You can search for your operator on Hoogle, and see that it is called (>=>). Its definition in terms of (>>=) is quite simple:

f >=> g = \x -> f x >>= g

In some sense (>=>) is better reflective of the idea to generalize composition, but I think (>>=) works better as a primitive operator simply because it's practical in more cases, and easier to relate to do-notation.


Could someone explain the reasoning behind this choice of definition for bind?

Sure, and it's almost exactly the same reasoning you have. It's just... we wanted a more general application operator, not a more general composition operator. If you've done much (any) point-free programming, you'll immediately recognize why: point-free programs are hard to write, and incredibly hard to read, compared to pointful ones. For example:

h x y = f (g x y)

With function application, this is completely straightforward. What's the version that only uses function composition look like?

h = (f .) . g

If you don't have to stop and stare for a minute or two the first time you see this, you might actually be a computer.

So, for whatever reason: our brains are wired to work a bit better with names and function application out of the box. So here's what the rest of your argument looks like, but with application in place of composition. If I have a function and an argument:

f :: a -> b
x :: a

the application operator should satisfy

h = x & f :: b

and from this I can infer the correct type of the & operator:

(&) :: a -> (a -> b) -> b

When it comes to monads, suppose my function and argument are monadic:

f :: a -> m b
x :: m a

The natural choice is to define a generalized application operator that works as follows:

h = x >>= f :: m b

in which case the >>= operator would have a type signature of:

(>>=) :: m a -> (a -> m b) -> m b