# 应用仿函数评估对我来说并不清楚

Allen Han 3 haskell functional-programming applicative

``````ghci> (+) <\$> (+3) <*> (*100) \$ 5
508
``````

Robin Zigmon.. 7

The other two answers have given the detail of how this is calculated - but I thought I might chime in with a more "intuitive" answer to explain how, without going through a detailed calculation, one can "see" that the result must be 508.

As you implied, every `Applicative` (in fact, even every `Functor`) can be viewed as a particular kind of "context" which holds values of a given type. As simple examples:

• `Maybe a` is a context in which a value of type `a` might exist, but might not (usually the result of a computation which may fail for some reason)
• `[a]` is a context which can hold zero or more values of type `a`, with no upper limit on the number - representing all possible outcomes of a particular computation
• `IO a` is a context in which a value of type `a` is available as a result of interacting with "the outside world" in some way. (OK that one isn't so simple...)

And, relevant to this example:

• `r -> a` is a context in which a value of type `a` is available, but its particular value is not yet known, because it depends on some (as yet unknown) value of type `r`.

The `Applicative` methods can be very well understood on the basis of values in such contexts. `pure` embeds an "ordinary value" in a "default context" in which it behaves as closely as possible in that context to a "context-free" one. I won't go through this for each of the 4 examples above (most of them are very obvious), but I will note that for functions, `pure = const` - that is, a "pure value" `a` is represented by the function which always produces `a` no matter what the source value.

Rather than dwell on how `<*>` can best be described using the "context" metaphor though, I want to dwell on the particular expression:

``````f <\$> a <*> b
``````

where `f` is a function between 2 "pure values" and `a` and `b` are "values in a context". This expression in fact has a synonym as a function: liftA2. Although using the `liftA2` function is generally considered less idiomatic than the "applicative style" using `<\$>` and `<*>`, the name emphasies that the idea is to "lift" a function on "ordinary values" to one on "values in a context". And when thought of like this, I think it is usually very intuitive what this does, given a particular "context" (ie. a particular `Applicative` instance).

So the expression:

``````(+) <\$> a <*> b
``````

for values `a` and `b` of type say `f Int` for an Applicative `f`, behaves as follows for different instances `f`:

• if `f = Maybe`, then the result, if `a` and `b` are both `Just` values, is to add up the underlying values and wrap them in a `Just`. If either `a` or `b` is `Nothing`, then the whole expression is `Nothing`.
• if `f = []` (the list instance) then the above expression is a list containing all sums of the form `a' + b'` where `a'` is in `a` and `b'` is in `b`.
• if `f = IO`, then the above expression is an IO action that performs all the I/O effects of `a` followed by those of `b`, and results in the sum of the `Int`s produced by those two actions.

So what, finally, does it do if `f` is the function instance? Since `a` and `b` are both functions describing how to get a given `Int` given an arbitrary (`Int`) input, it is natural that lifting the `(+)` function over them should be the function that, given an input, gets the result of both the `a` and `b` functions, and then adds the results.

And that is, of course, what it does - and the explicit route by which it does that has been very ably mapped out by the other answers. But the reason why it works out like that - indeed, the very reason we have the instance that `f <*> g = \x -> f x (g x)`, which might otherwise seem rather arbitrary (although in actual fact it's one of the very few things, if not the only thing, that will type-check), is so that the instance matches the semantics of "values which depend on some as-yet-unknown other value, according to the given function". And in general, I would say it's often better to think "at a high level" like this than to be forced to go down to the low-level details of exactly how computations are performed. (Although I certainly don't want to downplay the importance of also being able to do the latter.)

[实际上，从哲学的角度来看，更确切地说，定义是正确的，只是因为类型检查是“自然的”定义，而实例恰好是碰巧的巧合，一个不错的“意思”。当然，数学充满了如此快乐的“巧合”，事实证明它们背后有很深的原因。]

Bergi.. 6

``````(+) <\$> (+3) <*> (*100) \$ 5
``````

```( (\a->b->a+b) <\$> (\c->c+3) <*> (\d->d*100) ) 5
( (\x -> (\a->b->a+b) ((\c->c+3) x)) <*> (\d->d*100) ) 5
( (\x -> (\a->b->a+b) (x+3)) <*> (\d->d*100) ) 5
( (\x -> b -> (x+3)+b) <*> (\d->d*100) ) 5
( (\x->b->(x+3)+b) <*> (\d->d*100) ) 5
(\y -> ((\x->b->(x+3)+b) y) ((\d->d*100) y)) 5
(\y -> (b->(y+3)+b) (y*100)) 5
(\y -> (y+3)+(y*100)) 5
(5+3)+(5*100)
```

Willem Van O.. 6

``````instance Functor ((->) r) where
fmap = (.)

instance Applicative ((->) a) where
pure = const
(<*>) f g x = f x (g x)
liftA2 q f g x = q (f x) (g x)
``````

`````` (+) <\$> (+3) <*> (*100)  \$ 5
``````

``````((+) <\$> (+3)) <*> (*100) \$ 5
``````

``````(+) . (+3)
``````

``````((+) . (+3)) <*> (*100) \$ 5
``````

``````\x -> ((+) . (+3)) x ((*100) x)
``````

``````\x -> ((+) (x+3)) ((*100) x)
``````

``````\x -> (+) (x+3) ((*100) x)
``````

``````\x -> (x+3) + 100 * x
``````

``````\x -> 101 * x + 3
``````

``````(\x -> 101*x + 3) 5
``````

``````101 * 5 + 3
``````

``````505 + 3
``````

``````508
``````

 归档时间： 1 年，2 月 前 查看次数： 209 次 最近记录： 1 年，2 月 前