在Haskell中研究仿函数,应用仿函数和monad,我在Wikipedia找到了这个定义:
在函数式编程中,特别是Haskell,一个 applicative 仿函数是一个类似 monad 的结构(
return
,fmap
,join
) 没有join
,或者像仿函数一样return
。
我无法理解:在我看来,向仿函数提供return
(即pure
)不足以获得一个应用仿函数,因为你需要提供{{1 } {(ap
)也是,不能仅根据<*>
和fmap
来定义。我错过了什么或者维基百科的定义不是绝对正确的吗?
编辑2017-02-08:我在this回答中找到了有关此问题的其他有用见解。
答案 0 :(得分:9)
文章不正确。假设我们有一个没有m
的monad join
或一个return
的仿函数。我们可以立即定义pure
:
pure :: Monad m => a -> m a
pure = return
但是,我们无法仅(<*>)
和fmap
定义return
。我们所拥有的只是fmap
,因此如果我们尝试使用m (m a)
,我们最终会得到m (a -> b)
。那时我们需要join
或其等效的(>>=)
:
(<*>) :: Monad m => m (a -> b) -> m a -> m b
f <*> x = join (fmap (flip fmap x) f)
-- or, easier to read:
-- f <*> x = do
-- f' <- f
-- x' <- x
-- return f' x'
应用仿函数就像一个return
和ap
的仿函数,但没有join
。所以,是的,你是完全正确的,维基百科错过了应用程序的运作(见the original paper)。
顺便说一句,如果您只添加pure
,则会获得pointed functor。尽管如此,typeclassopedia提供了比{1}}更好的概述,而不是维基百科的文章。
答案 1 :(得分:7)
你是对的,应用函子需要<*>
以及pure
来获得最小的定义。值得注意的是,我们可以从这些中获得fmap
:
fmap f a = pure f <*> a
同样,我们可以从monads获得适用的定义:
pure = return
f' <*> a' = do
f <- f'
a <- a'
return $ f a
您可以查看applicatives仿函数,将仿函数概括为多参数函数,或者将值与水平上下文相结合:
liftA2 f a b = f <$> a <*> b
fmap :: (a -> b) -> (f a -> f b)
liftA2 :: (a -> b -> c) -> (f a -> f b -> f c)