我无法理解维基百科对 "applicative functor" 的定义

I can't understand Wikipedia's definition of "applicative functor"

研究 Haskell 中的函子、应用函子和单子,我在 Wikipedia 上找到了这个定义:

In functional programming, specifically Haskell, an applicative functor is a structure that is like a monad (return, fmap, join) without join, or like a functor with return.

我无法理解:在我看来,向函子提供return(即pure)不足以获得应用函子,因为您需要提供ap(即 <*>),不能仅根据 fmapreturn 来定义。是我遗漏了什么还是维基百科的定义不完全正确?

编辑 2017-02-08:我在 答案中找到了关于这个问题的其他有用见解。

你是对的,应用仿函数需要 <*>pure 来获得最小定义。值得注意的是,我们可以从中得到 fmap,不过:

fmap f a = pure f <*> a

同样我们可以从monads中得到应用定义:

pure = return
f' <*> a' = do
    f <- f'
    a <- a'
    return $ f a

您可以查看应用仿函数,仿函数对多参数函数的泛化,或者将值与上下文水平组合:

liftA2 f a b = f <$> a <*> b
fmap :: (a -> b) -> (f a -> f b)
liftA2 :: (a -> b -> c) -> (f a -> f b -> f c)

这篇文章不正确。假设我们有一个没有 join 的单子 m,或者一个有 return 的仿函数。我们可以立即定义pure

pure :: Monad m => a -> m a
pure = return

但是,我们不能只用 fmapreturn 来定义 (<*>)。我们只有 fmap,所以如果我们尝试使用 m (a -> b),我们最终会得到 m (m a)。那时我们需要 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'

应用函子就像一个有 returnap 但没有 join 的函子。所以是的,你是完全正确的,维基百科错过了 applicative 的操作(参见 the original paper)。

顺便说一下,如果您只添加 pure,您会得到一个 pointed functor. The typeclassopedia 提供比维基百科文章更好的 Applicative 概述。