Applicative Functor 中 `pure` 的用途是什么

What is the purpose of `pure` in Applicative Functor

Meet the Applicative typeclass. It lies in the Control.Applicative module and it defines two methods, pure and <*>. It doesn't provide a default implementation for any of them, so we have to define them both if we want something to be an applicative functor.

我想了解谁在使用 pure 功能。我确实使用应用函子最有用的 (<*>) 函数。但我不确定谁真正使用 pure.

我读到类似 pure (+3) <*> Just 10 的东西,但它也可以写成 Just (+3) <*> Just 10

以上只是我有太多困惑中的一个。定义 pure 的真正目的是什么?我什么时候可以使用它(或)谁已经在使用它?

<*> :: f (a -> b) -> f a -> f b,这个运算符接受一个应用类型的函数,以及一个应用类型的值。因此,此运算符的第一个参数不能只是一个函数,但它必须驻留在一个应用程序中。

pure函数解决了这里可能出现的问题(例如,想要应用一个不在applicative中的函数)。它接受一个当前不在应用程序中的函数,并将其提升到应用程序中。pure :: a -> f a

(+3) :: Int -> IntJust 10 :: Maybe Int,您不能因此评估 (+3) <*> Just 10,因为类型不起作用; (+3) 必须提升为 Maybe 应用程序中的值。

对于Maybe apure的定义是pure = Just,这就是为什么你可以写成pure (+3)Just (+3)

--

我会留给你研究 <$> 运算符 :-) 请记住,每个 Applicative 都是一个 Functor。

pure 就像 mempty 对应 Monoidmemptymappend 持中立态度。 pure 对于 <*> 也是中性的(在某种意义上),它在没有任何效果的情况下提升了函子的一些价值,或者提升了中性效果。

这句话可以用四个属性形式化(copy/past 来自 Applicative 上的文档):

pure id <*> v = v
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
pure f <*> pure x = pure (f x)
u <*> pure y = pure ($ y) <*> u

What is the true purpose of defining pure and when do I get to use it (or) who is already using it?

嗯,基本上是为了写更通用的代码。例如:

when :: Applicative f => Bool -> f () -> f ()
when p s = if p then s else pure ()

sequenceA_ :: Applicative f => [f a] -> f ()
sequenceA_ = foldr (*>) (pure ())

traverse_ :: Applicative f => (a -> f b) -> [a] -> f ()
traverse_ f = foldr ((*>) . f) (pure ())

此外,有时使用起来更简单 pure 然后将值隐式包装到函子。例如,比较:

pure 3 ~ StateT (\s -> Identity (3, s))

有几种情况可以使用pure

  1. 正如 freestyle 的答案所示,当您不知道正在使用什么特定 Applicative 时。

  2. 也是freestyle的,只是用起来更方便pure

除了在某些情况下更易于编写之外,它还可以使您的代码更健壮。在我开发软件时,我的关键数据结构经常发生变化。使用 pure 而不是特定的构造函数有助于创建在重构期间可以保持不变的代码点。

  1. 具体Applicative执行时不可用。

有时库不会为其数据类型导出构造函数。相反,它们依靠函数来构建类型的有效实例。使该类型成为 Applicative 的成员是一种方法。 IO Monad (Applicative) 是构造函数不可用的类型的另一个示例。相反,我们被迫使用 pure(又名 return)。