简体   繁体   English

Haskell:了解应用函子的纯函数

[英]Haskell: Understanding the pure function for Applicative functors

I am learning about Applicative Functors and the pure function has the following type declaration: 我正在学习Applicative Functors,并且pure函数具有以下类型声明:

pure :: a -> f a 

I understand that the pure function takes a value of any type and returns an applicative value with that value inside it. 我知道pure函数可以接受任何类型的值,并返回其中包含该值的适用值。 So if the applicative instance was Maybe , pure 3 would give Just 3 . 因此,如果适用实例是Maybe ,则pure 3会得到Just 3

However, what happens when you apply pure to a value that's already inside an applicative value? 但是,当您将纯值应用到应用值中已经包含的值时会发生什么? Eg what happens if you do something like pure Just 3 ? 例如,如果您执行pure Just 3怎样?

What happens when you apply pure to a value that's already inside an applicative value? 如果将纯值应用于已经在应用值内的值,会发生什么?

It just gets wrapped in an additional layer. 它只是包裹在一个附加层中。 The end result is an applicative value nested inside another applicative value. 最终结果是一个嵌套在另一个应用程序值内的应用程序值。

Eg what happens if you do something like pure Just 3 ? 例如,如果您执行pure Just 3怎样?

This is an interesting question, although probably not for the reasons you meant. 这可能是一个有趣的问题,尽管可能并非出于您的意思。 The important point here is to distinguish pure (Just 3) — which was probably what you meant — from pure Just 3 = (pure Just) 3 , which is what you wrote. 这里的重点是要区分pure (Just 3) (这可能是您的意思)与pure Just 3 = (pure Just) 3 (您写的是)。 This gives two scenarios: 这给出了两种情况:

  • pure (Just 3) simply applies pure to the value Just 3 , which — as I discussed above — gives Just (Just 3) , which is a nested applicative value. pure (Just 3)只是将pure应用于值Just 3 ,正如我上面所讨论的,它给出了Just (Just 3) ,它是一个嵌套的应用值。
  • (pure Just) 3 is an interesting case. (pure Just) 3是一个有趣的案例。 Recall the types of pure and Just : 回想一下pureJust的类型:

     pure :: Applicative f => a -> fa Just :: a -> Maybe a -- so: pure Just :: Applicative f => f (a -> Maybe a) 

    In other words, pure Just takes the function Just and wraps it inside an applicative value. 换句话说, pure Just取功能Just和包装它的应用价值内。

    Next, we want to take pure Just and apply it to a value 3 . 接下来,我们要采用pure Just并将其应用于值3 But we can't do this, since f (a -> Maybe a) is a value, not a function! 但是我们不能这样做,因为f (a -> Maybe a)是一个值,而不是一个函数! So (pure Just) 3 should result in a type error. 因此(pure Just) 3应该导致类型错误。

    …except it turns out to typecheck just fine! …除了事实证明可以进行类型检查! So we're missing something. 因此,我们缺少了一些东西。 In this case, it turns out there is an applicative instance for functions: 在这种情况下,事实证明有一个函数的应用实例:

     instance Applicative ((->) r) where pure x = \\r -> x (<*>) = _irrelevant_here 

    The syntax is a bit funny, but it basically means that r -> ... is an applicative. 语法有点可笑,但是它基本上意味着r -> ...是可应用的。 This particular instance is known as the Reader monad , and it's very widely used. 这个特定的实例称为Reader monad ,它被广泛使用。 (For more about this particular data type, see eg here or here .) The idea is that r -> a can compute an a given an r input; (有关该特定数据类型的,例如参见这里这里 。)的想法是, r -> a可以计算的a给定的r输入; in this case, pure x creates a function which ignores its input and returns x always, and f <*> x feeds the r input into both f and x , then combines the two. 在这种情况下, pure x创建一个忽略其输入并始终返回x的函数,并且f <*> xr输入馈入fx ,然后将两者组合。 In this case, we're only using pure , so it's easy to evaluate (pure Just) 3 by hand: 在这种情况下,我们仅使用pure ,因此很容易手动评估(pure Just) 3

     (pure Just) 3 = (\\r -> Just) 3 = Just 

    So the idea here is that pure wraps Just in an applicative value, which in this case happens to be a function; 因此,这里的想法是, pureJust包装在一个应用值中,在这种情况下,它恰好是一个函数。 then, we apply this function to 3 , which gets rid of the wrapper to reveal the original Just . 然后,将此函数应用于3 ,该函数将摆脱包装器以显示原始Just

First of all, pure has the type: 首先,pure具有以下类型:

pure :: Applicative f => a -> f a

To make things simpler, think of the kind of f 为简化起见,请考虑f

:k f 
f :: * -> *

and the kind of a is * a的种类是*

then the type of a , is just a , any a , the most polymorphic of all (but with kind * remember). 然后类型a ,仅仅是a ,任何a最多态性所有的(但有一种*记得了)。 So you don't really care the value of a, you just have a restriction, and that's the typeclass Applicative, and the kind of f (remember * -> * ) 因此,您实际上并不在乎a的值,只是有一个限制,那就是typeclass Applicative和f的种类(请记住* -> *

so in this case: 所以在这种情况下:

gchi> pure 3 :: Maybe Int
ghci> Just 3

here f is Maybe and a is 3 这里f Maybe是, a3

In the same way 以同样的方式

gchi> pure $ Just 3 :: Maybe (Maybe Int)
gchi> Just (Just 3)

here f is again Maybe and a is Just 3 在这里fMaybe是,而a Just 3

and you can play a little changing the type to pure: 然后您可以将类型更改为pure:

gchi> pure 3 :: [Double]
ghci> [3.0]

here, f is [], and a is 3 在这里, f是[], a3

same way 同样的方式

ghci> pure [3] :: [[Double]]
ghci> [[3.0]]

finally here, f again, is [] and a is [3] 终于在这里, f又是[]a是[3]

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

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