为Monad实现Applicative(<*>)

Kev*_*ith 4 haskell

Applicative有这个(<*>)功能:

(<*>) :: (Applicative f) => f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

了解您的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
Run Code Online (Sandbox Code Playgroud)

怎么可以ap单独写bind,即>>=

我不知道如何提取(a -> b)m (a -> b).也许一旦我理解了它的<-作用do notation,我就会理解上述问题的答案.

Sib*_*ibi 8

怎么能用bind单独写,即>> =?

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

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap xs a = xs >>= (\f -> liftM f a)
Run Code Online (Sandbox Code Playgroud)

如果你不想甚至使用liftM那么:

ap :: (Monad m) => m (a -> b) -> m a -> m b
ap mf ma = mf >>= (\f -> ma >>= (\a' -> return $ f a'))
Run Code Online (Sandbox Code Playgroud)

最初这些是类型:

mf  :: m (a -> b)
ma  :: m a
Run Code Online (Sandbox Code Playgroud)

现在,当您将bind(>>=)运算符应用于mf:时mf >>= (\f-> ...,f其类型为:

f :: (a -> b)
Run Code Online (Sandbox Code Playgroud)

在下一步中,ma也适用于>>=:ma >>= (\a'-> ...,这里a'有以下类型:

a' :: a
Run Code Online (Sandbox Code Playgroud)

所以,现在当你申请时f a',你得到的类型b是因为:

f    :: (a -> b)
a'   :: a
f a' :: b
Run Code Online (Sandbox Code Playgroud)

并应用returnf a'将与单子层包裹它,因此最终的类型,你得到的将是:

return (f a') :: m b
Run Code Online (Sandbox Code Playgroud)

因此,所有的东西都会出现问题.

  • 你为什么用`~`而不是`::`? (3认同)