了解你一个Haskell引入了以下定义的第11章:
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
下面,笔者在一些不寻常的挥手从事(“实例实施<*>是一个有点神秘,所以它的最好的,如果我们只[在行动表明它没有解释原因]”)。 我希望这里有人可能会帮助我找到答案。
根据应用性类的定义, (<*>) :: f (a -> b) -> fa -> fb
在该实例,用((->)r)
为f
: r->(a->b)->(r->a)->(r->b)
所以,第一个问题,就是如何从该类型得到f <*> g = \x -> fx (gx)
但即使我采取的最后一个公式是理所当然的,我有麻烦使其与例子我给GHCI同意。 例如:
Prelude Control.Applicative> (pure (+5)) <*> (*3) $ 4
17
该表达式代替出现一致f <*> g = \x -> f (gx)
请注意,在这个版本x
之后不会出现f
。
我意识到这是凌乱的,所以感谢您与我的轴承。
首先,记得fmap
为applicatives定义:
fmap f x = pure f <*> x
这意味着你的例子是一样的(fmap (+ 5) (* 3)) 4
。 该fmap
为功能的功能只是组合物,所以你的精确表达式是相同的((+ 5) . (* 3)) 4
。
现在,让我们想想为什么实例写到事情是这样的。 什么<*>
做本质上是在仿函数应用在仿函数的值。 专业到(->) r
,这意味着它适用从由函数返回的函数r
通过从函数返回一个值r
返回功能的功能仅仅是一个两个参数的功能。 所以,真正的问题是:你会如何运用的两个参数(函数r
和a
,返回b
)的值a
由函数返回r
首先要注意的事情是,你必须返回类型的值(->) r
,这意味着其结果也必须从函数r
作为参考,这里是<*>
功能:
f <*> g = \x -> f x (g x)
因为我们要返回一个函数取类型的值r
x :: r
我们返回函数必须有一个类型r -> b
。 我们怎样才能类型的值b
? 好了,我们有一个功能f :: r -> a -> b
。 由于r
将是该结果函数的参数,我们得到的是免费的。 所以,现在我们已经从一个函数a -> b
。 所以,只要我们有类型的一些价值a
,我们可以得到类型的值b
。 但是,我们如何获得类型的值a
? 好了,我们有另一个功能g :: r -> a
。 因此,我们可以把我们的类型值r
参数x
),并用它来获得类型的值a
。
所以最终的想法很简单:我们使用的参数,首先要获得类型的值a
将其插入g
。 该参数具有键入r
g
具有类型r -> a
,所以我们有一个a
。 然后,我们既插既参数和新值f
。 我们既需要,因为f
有型r -> a -> b
。 一旦我们既插既一个r
和a
在,我们有一个b1
。 由于参数是一个lambda,结果有一个类型r -> b
,这是我们想要的。
通过你原来的问题去,我认为有,你可能会错过一个微妙但很关键的一点。 使用从LYAH最初的例子:
(+) <$> (+3) <*> (*100) $ 5
这是一样的:
pure (+) <*> (+3) <*> (*100) $ 5
这里的关键是pure
前(+)
其具有拳击的效果(+)
作为应用型。 如果你看一下如何pure
的定义,你可以看到,拆箱,你需要提供一个额外的参数,它可以是任何东西。 应用<*>
以(+) <$> (+3)
我们得到
\x -> (pure (+)) x ((+3) x)
注意在(pure (+)) x
,我们正在申请x
到pure
拆箱(+)
所以我们现在有
\x -> (+) ((+3) x)
添加(*100)
获得(+) <$> (+3) <*> (*100)
并应用<*>
再次,我们得到
\y -> (\x -> (+) ((+3) x)) y ((*100) y) {Since f <*> g = f x (g x)}
5 -> (\x -> (+) ((+3) x)) 5 ((*100) 5)
(\x -> (+) ((+3) x)) 5 (500)
5 -> (+) ((+3) 5) (500)
(+) 8 500
508
所以在最后,在x
之后f
不是第一个参数我们的二元运算符,它是用来拆箱操作中pure
。
“以实例,用((->)r)
为f
: r->(a->b)->(r->a)->(r->b)
”
为什么,那是不对的。 它实际上是(r->(a->b)) -> (r->a) -> (r->b)
,这是相同的(r->a->b) -> (r->a) -> r -> b
。 即,我们映射中缀和返回缀“右手的说法,到只需缀的函数” LHS并返回其结果的函数。 例如,
Prelude Control.Applicative> (:) <*> (\x -> [x]) $ 2
[2,2]