简体   繁体   English

Applicative Functor中`pure`的目的是什么?

[英]What is the purpose of `pure` in Applicative Functor

Meet the Applicative typeclass. 符合Applicative类型类。 It lies in the Control.Applicative module and it defines two methods, pure and <*> . 它位于Control.Applicative模块中,它定义了两个方法, 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. 它没有为它们中的任何一个提供默认实现,因此如果我们想要某些东西成为一个applicative functor,我们必须定义它们。

I am trying to understand who is using pure function. 我试图了解谁在使用pure函数。 I do use (<*>) function for which applicative functors are most useful for. 我使用(<*>)函数,其中applicative functor最有用。 But I am not sure who really uses pure . 但我不确定谁真的使用pure

I read something like pure (+3) <*> Just 10 but it can be written as Just (+3) <*> Just 10 too. 我读过类似pure (+3) <*> Just 10东西pure (+3) <*> Just 10但它可以写成Just (+3) <*> Just 10

Above is just one confusion of too many I have. 以上只是我有太多困惑。 What is the true purpose of defining pure and when do I get to use it (or) who is already using it? 定义pure的真正目的是什么?我何时使用它(或)已经使用它?

<*> :: f (a -> b) -> fa -> fb , this operator accepts a function in the applicative type, as well as a value in the applicative type. <*> :: f (a -> b) -> fa -> fb ,此运算符接受applicative类型中的函数,以及applicative类型中的值。 The first argument of this operator can not thus be simply a function, but it has to be residing within an applicative. 因此,此运算符的第一个参数不能仅仅是一个函数,而是必须驻留在一个应用程序中。

The pure function solves problems that might occur here (eg wanting to apply a function that is not residing in the applicative). pure函数解决了此处可能出现的问题(例如,想要应用不存在于应用程序中的函数)。 It accepts a function that is not currently residing in the applicative, and lifts it into the applicative. 它接受一个当前不在应用程序中的函数,并将其提升到应用程序中。 pure :: a -> fa

(+3) :: Int -> Int , and Just 10 :: Maybe Int , you can not thus evaluate (+3) <*> Just 10 as the types do not work; (+3) :: Int -> Int ,和Just 10 :: Maybe Int ,你不能这样评价(+3) <*> Just 10因为类型不起作用; the (+3) has to be promoted to a value in the Maybe applicative. 必须将(+3)提升为Maybe applicative中的值。

For Maybe a , the definition of pure is pure = Just , which is why you can write either pure (+3) or Just (+3) 对于Maybe apure的定义是pure = Just ,这就是为什么你可以编写pure (+3)Just (+3)

-- -

I'll leave it to you to look into the <$> operator :-) Remember, every Applicative is a Functor. 我会留给你看看<$>运算符:-)请记住,每个Applicative都是一个Functor。

pure is like mempty for Monoid . pure就像Monoid mempty mempty is neutral for mappend . mempty对于mappend mempty是中立的。 pure is also neutral (in some sence) for <*> , it lifts some value to the functor without any effects or lifts with neutral effect. 对于<*>pure也是中性的(在某些情况下),它会将一些值提升到仿函数而没有任何效果或具有中性效果的提升。

This sentence can be formalized with four properties (copy/past from docs on Applicative ): 这句话可以用四个属性形式化(复制/过去来自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? 定义纯粹的真正目的是什么?我何时使用它(或)已经使用它?

Well, basically for writing more generalized code. 好吧,基本上用于编写更通用的代码。 For example: 例如:

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 ())

Also, sometime more simpler to use pure then implicitly wrap a value to a functor. 此外,有时使用pure更简单,然后隐式地将值包装到仿函数。 For example, compare: 例如,比较:

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

There are a few situations to use pure . 有几种情况可以使用pure

  1. As freestyle's answer illustrated, when you don't know what specific Applicative is being used. 正如自由式的答案所示,当您不知道使用什么特定的Applicative

  2. Also from freestyle, when its just more convenient to use pure . 同样来自于自由泳,当它使用pure时更方便。

In addition to just being simpler to write in some cases, it can make your code more robust. 除了在某些情况下编写起来更简单之外,它还可以使您的代码更加健壮。 As I've develop software, my key data structures often evolve. 在开发软件时,我的关键数据结构经常发展。 Using pure instead of a specific constructor helps create spots of code that can remain unchanged during refactoring. 使用pure而不是特定的构造函数有助于创建在重构期间可以保持不变的代码点。

  1. When the implementation of the specific Applicative is unavailable. 当具体Applicative的实现不可用时。

Sometimes a library will not export constructors for their data types. 有时,库不会为其数据类型导出构造函数。 Instead they rely on functions to build valid instances of the types. 相反,他们依靠函数来构建类型的有效实例。 Making that type a member of Applicative is one way to do this. 使该类型成为Applicative的成员是一种方法。 The IO Monad (Applicative) is another example of a type for which a constructor just isn't available. IO Monad(Applicative)是构造函数不可用的类型的另一个示例。 Instead, we are forced to use pure (aka return ). 相反,我们被迫使用pure (又称return )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM