[英]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
: 回想一下
pure
和Just
的类型:
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 <*> x
将r
输入馈入f
和x
,然后将两者组合。 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; 因此,这里的想法是,
pure
将Just
包装在一个应用值中,在这种情况下,它恰好是一个函数。 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
是, a
是3
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
在这里
f
又Maybe
是,而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
是[], a
是3
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.