Monad key way is to look inside ma type and see a ; but the restriction of the Monad key is that for monads there should be “unrecoverable” possible, that is, operations of the Monad type should not be sufficient to write a function of the Monad m => ma -> a type Monad m => ma -> a . (>>=) :: Monad m => ma -> (a -> mb) -> mb gives you exactly this ability.
But there is more than one way to achieve this. The Monad class can be defined as follows:
class Functor f where fmap :: (a -> b) -> fa -> fb class Functor f => Monad m where return :: a -> ma join :: m (ma) -> ma
You ask why we cannot have the function Monad m => ma -> (ma -> mb) -> mb . Well, given f :: a -> b , fmap f :: ma -> mb is basically that. But fmap alone does not give you the opportunity to "look inside" Monad m => ma , but cannot escape from it. However, join and fmap together give you this ability. (>>=) can be written in general terms with fmap and join :
(>>=) :: Monad m => ma -> (a -> mb) -> mb ma >>= f = join (fmap f ma)
This is actually a common trick for defining an instance of Monad when you have trouble defining for (>>=) -write join for your potential monad, and then use the generic definition (>>=) .
Well, that answers the question, "should it be what it is," part of the no question. But why is it so?
I cannot speak for Haskell designers, but I like to think of it this way: in Haskell's monastic programming, the main building blocks are these actions:
getLine :: IO String putStrLn :: String -> IO ()
In general, these basic building blocks are of types that look like Monad m => ma , Monad m => a -> mb , Monad m => a -> b -> mc , ..., Monad m => a -> b -> ... -> mz . People informally call these actions. Monad m => ma - action without an argument, Monad m => a -> mb - action with one argument, etc.
Well, (>>=) :: Monad m => ma -> (a -> mb) -> mb is basically the simplest function that "binds" two actions. getLine >>= putStrLn is the action that getLine first executes and then putStrLn , passing it the result obtained from getLine . If you had fmap and join , and not >>= , you would have to write this:
join (fmap putStrLn getLine)
More generally (>>=) embodies a concept very similar to the "pipeline" of actions, and as such is a more useful operator for using monads as a kind of programming language.
The final thing: make sure you know the Control.Monad module. Although return and (>>=) are the main functions for monads, there are endless other higher-level functions that you can define using these two, and this module collects several dozen of the most common. Your code should not be transferred to a straitjacket on (>>=) ; it is an important building block that is useful both on its own and as a component for large building blocks.