Question

All apologies -- I'm still very much on the outside of Haskell looking in.

Why does the bind for a monad have this signature:

M a -> (a -> M b) -> M b

and not

M a -> (M a -> M b) -> M b

i.e. a function that takes M a instead of just a

a is available to the function in both, but the context that M provides is not available to the function in the 1st. Just the lifted value itself.

(If that's a silly question, just downvote me a lot & I'll delete it... like I say, still very much on the outside looking in)

Was it helpful?

Solution

Just a hint: a -> M b is more general than M a -> M b, since you can do a -> M a any time with return.

OTHER TIPS

Let’s call functions that return a monadic value “actions”.

The type signature for >>= in p >>= q says that:

  • Given a nullary action p that returns something of type a
  • And given a unary action q that takes an a and returns something of type b
  • You can chain them to get a nullary action that returns something of type b

It is worth remembering that >>= has a flipped version: =<<, that might be easier to understand visually—it corresponds to function application in a monad:

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

Whereas $ is application of a pure function to a pure argument:

succ $ 2 + 2

=<< is application of a side-effectful function to a side-effectful argument:

putStrLn =<< readLine

And you may have seen the Applicative operator <$> (an alias for fmap), which is for the other common case of pure functions with side-effecting arguments:

lines <$> readFile "input.txt"
Licensed under: CC-BY-SA with attribution
scroll top