Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Applicative's (<*>) for Monad

Tags:

haskell

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.

like image 689
Kevin Meredith Avatar asked Feb 13 '23 04:02

Kevin Meredith


1 Answers

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.

like image 128
Sibi Avatar answered Feb 24 '23 12:02

Sibi