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