为Monad实施Applicative(< *>)

时间:2014-08-24 15:03:00

标签: haskell

Applicative具有(<*>)功能:

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

Learn You a Haskell显示以下功能。

假设:

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

如何ap单独使用bind撰写,>>=

我不确定如何从(a -> b)中提取m (a -> b)。也许一旦我理解了<- do notation的工作原理,我就能理解上述问题的答案。

1 个答案:

答案 0 :(得分:8)

  

如何使用bind单独编写,即&gt;&gt; =?

这是我可以提出的一个示例实现:

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

如果您不想使用liftM,那么:

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

最初这些是类型:

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

现在,当您将绑定(>>=)运算符应用于mfmf >>= (\f-> ...时,f的类型为:

f :: (a -> b)

在下一步中,ma也适用于>>=ma >>= (\a'-> ...,此处a'的类型为:

a' :: a

因此,现在当您应用f a'时,您会从中获得b类型,因为:

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

你将return应用于f a',它将用monadic图层包裹它,因此你得到的最终类型将是:

return (f a') :: m b

因此,所有的事情都会出现问题。