如适用函数的黑客中提到的那样,它们是强大的松散单曲面函数。那么,为什么它们在Haskell中的定义却不这样显示:
class Functor f => MonoidalApplicative f where
mult :: f a -> f b -> f (a,b)
unit :: a -> f a
starAp :: f (a -> b) -> f a -> f b
starAp h x = fmap (uncurry ($)) (mult h x)
Run Code Online (Sandbox Code Playgroud)
<*>(starAp)可以很容易地按照乘法来重构,这个定义对我来说更简单。例如,这是Maybe实例:
instance MonoidalApplicative Maybe where
mult (Just x) (Just y) = Just (x,y)
mult _ _ = Nothing
unit x = Just x
Run Code Online (Sandbox Code Playgroud) 我最近在Exercism上为ISBN Verifier练习编写了一个解决方案,当我通过pointfree.io运行这个函数时:
\c -> isDigit c || c == 'X'
Run Code Online (Sandbox Code Playgroud)
我回来了:
liftM2 (||) isDigit ('X' ==)
Run Code Online (Sandbox Code Playgroud)
为什么pointfree.io选择liftM2从Control.Monad,而不是liftA2从Control.Applicative?
我查看过去的讨论,但无法理解为什么任何答案都是正确的.
合用的
<*> :: f (a -> b) -> f a -> f b
单子
(>>=) :: m a -> (a -> m b) -> m b
因此,如果我做对了,那么声称是>>=不能仅仅假设存在而写的<*>
好吧,让我们假设我有<*>.
我想创造>>=.
所以我有f a.
我有f (a -> b).
现在当你看它时,f (a -> b)可以写成(a -> b)(如果某个东西是x,y,z的函数 - 那么它也是x,y的函数).
所以从<*>我们得到的存在(a -> b) -> f a -> f b再次可以写成((a -> b) -> f a) …