4

Applicative's has the (<*>) function:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b

Learn You a Haskell shows the following function.

Given:

ap :: (Monad m) => m (a -> b) -> m a -> m b  
ap f m = do
  g <- f        -- '<-' extracts f's (a -> b) from m (a -> b)
  m2 <- m       -- '<-' extracts a from m a 
  return (g m2) -- g m2 has type `b` and return makes it a Monad

How could ap be written with bind alone, i.e. >>=?

I'm not sure how to extract the (a -> b) from m (a -> b). Perhaps once I understand how <- works in do notation, I'll understand the answer to my above question.

MasterMastic
  • 20,711
  • 12
  • 68
  • 90
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384
  • 2
    There are quite a few questions on SO about desugaring do-notation that might help you. I think my answer (http://stackoverflow.com/questions/7229518/how-to-write-without-do-notation/7229732#7229732) is good obviously, but there are others too. – John L Aug 24 '14 at 19:59

1 Answers1

8

How could ap be written with bind alone, i.e. >>= ?

This is one sample implementation I can come up with:

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap xs a = xs >>= (\f -> liftM f a)

Of if you don't want to even use liftM then:

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap mf ma = mf >>= (\f -> ma >>= (\a' -> return $ f a'))

Intially these are the types:

mf  :: m (a -> b)
ma  :: m a

Now, when you apply bind (>>=) operator to mf: mf >>= (\f-> ..., then f has the type of:

f :: (a -> b)

In the next step, ma is also applied with >>=: ma >>= (\a'-> ..., here a' has the type of:

a' :: a

So, now when you apply f a', you get the type b from that because:

f    :: (a -> b)
a'   :: a
f a' :: b

And you apply return over f a' which will wrap it with the monadic layer and hence the final type you get will be:

return (f a') :: m b

And hence everything typechecks.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Sibi
  • 47,472
  • 16
  • 95
  • 163
  • could you please explain how `\f -> a >>= \a' -> return $ f a'` has a type of `a -> m b`? I'm not understanding `f`'s type & how you're applying it to `a'`. – Kevin Meredith Aug 24 '14 at 15:23
  • @KevinMeredith I have change the variables name to avoid confusion and have added explanation. Let me know if something confuses you. – Sibi Aug 24 '14 at 15:32
  • 3
    Why are you using `~` instead of `::`? – Tom Ellis Aug 24 '14 at 16:21