CSnerd
CSnerd

Reputation: 2229

How does Monad conform to the composition of function

I know the functions are all about composition. For example, if I have an arrow from A to B and an arrow from B to C, composition means I also have an arrow from A to C.

But for (>>=), its type is Monad m => m a -> (a -> m b) -> m b. Why m a is equal to a here?

I was wondering why not Monad m => m a -> (m a -> m b) -> m b? Does this make more sense?

Upvotes: 3

Views: 210

Answers (4)

Jon Purdy
Jon Purdy

Reputation: 54971

>>= does not correspond to composition, it corresponds to (flipped) application. The flipped version =<< makes this clear:

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

($) takes a unary function and applies it to a value, giving a value; =<< takes a unary action and applies it to the result of a nullary action, giving a nullary action.

The operators corresponding to composition are <=< and >=> from Control.Monad:

(.)   ::              (b ->   c) -> (a ->   b) -> a ->   c
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c

(.) composes two unary functions, giving a unary function; <=< composes two unary actions, giving a unary action.

Upvotes: 5

jamshidh
jamshidh

Reputation: 12060

If you reorder the type signature, it would make a lot more sense to you....

Let modify be (>>=) with flipped order

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

or, adding implied parentheses

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

Now it is clear what is happening.... We are given a "lopsided" function that can't be placed in a pipeline of fixed data type, and converting it to a function that can.... These functions are nicer to deal with, as you can add and remove them at will to the pipeline, apply N times, even reorder them. (well, for a=b, at least)

The pattern is very common.... a->m b, for instance, could be a function that takes a val, and may or may not return a value or error.

Upvotes: 1

Stephen Diehl
Stephen Diehl

Reputation: 8409

@Sibi's answer is right, it wouldn't make sense or be useful for monads to be defined like the second signature. But related to your question about relation between function composition and monadic composition, there is an alternative way of looking at the operator.

Monads have a bunch of alternative constructions equivalent to the bind/return formulation. One of them is in terms of an operator (<=<) called the Kleisli composition operator that composes monadic operations in a structurally similar way to how functions compose.

Arrows:

Functions          : a -> b
Monadic operations : a -> m b

Composition:

-- Function composition
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> g (f x)

-- Monad composition
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
f <=< g ≡ \x -> g x >>= f 

Gabriel Gonzalez wrote a nice blog post about this pattern: http://www.haskellforall.com/2012/08/the-category-design-pattern.html

Upvotes: 6

Sibi
Sibi

Reputation: 48644

Try to implement that function yourself and you will find that it would be useless:

func :: Monad m => m a -> (m a -> m b) -> m b
func x f = f x

So what you are basically suggesting is applying a value to a function. I don't think we need a special function for that. :-) The whole point of >>= is that it executes the side effect of it's first parameter and then passes the resultant value of it to the function.

Upvotes: 6

Related Questions