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,我就会理解上述问题的答案.
怎么能用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)
并应用return了f a'将与单子层包裹它,因此最终的类型,你得到的将是:
return (f a') :: m b
Run Code Online (Sandbox Code Playgroud)
因此,所有的东西都会出现问题.