3

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)

  • 2
    It's not a silly question. But tell me: how do we ever get at the a if only the M a is available? Assume we have no other ways except for bind to access the thing “inside” the monad. The bind is exactly this “accessor”, and the more interesting question is why it returns a M b instead of just a b. – amon Feb 26 '14 at 22:59
  • 1
    aha! OK I've been writing direct accessors (like Left/Right), but making that a requirement would be a sort of 4th monadic rule. I think I understand the M b part (admitting that I understand nothing about Haskell), because the action function needs to set up chaining in the monadic space. Otherwise, a) you'd always have to do bind + return and b) the action function might want to invoke M outside of b. For example, the bind function might want to call Left instead of Right, but (a -> b) wouldn't allow that. That's gotta be wrong, but I feel like I'm getting closer. – Rob Feb 27 '14 at 7:53
  • 1
    That's good! Actually, a function with the signature (a → b) → M a → M b exists as well : fmap. However, assume we want to write a filter that decides whether we include any element in the output. For example a List Monad: with bind, we can return item to keep, or the empty list [] to discard an item. With fmap we can do the same, but we would get a list of lists: [1, 2, 3, 4] might produce [[], [2], [], [4]] when filtering for even numbers. We need a flatten that outputs [2, 4] for fmap to be as general as bind. – amon Feb 27 '14 at 8:13
4

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.

5

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"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.