到目前为止我们已经知道了 Functor 可以将 effect 跟 pure function 进行 compose,但我们没有提到一点是 Functor 无法应付的,而今天要介绍的主角就是用来解决此一情境的,Apply。
f | g | composition |
---|---|---|
pure | pure | compose(f, g) |
effects | pure(unary) | f.map(g) |
effects | pure(n-ary) | ? |
举例来说,现在有两个 Identity,分别是 Identity(1)
跟 Identity(2)
,我们要如何将其进行相加
如果用一般正常函式的相加,看来是行不通
const add = (x, y) => x + y;
add(Identity.of(1), Identity.of(2)) // [object Object][object Object]
可能有读者想到, 如果用 map 将分别将 Identity 内的值取出,再将 add 在套用到取出後的值就好了
const result = Identity.of(1).map(x => Identity.of(2).map(y => add(x, y))) // Identity(Identity(3))
确实,这样也是一个办法,但这种方法不但会导致前後相依,也就是必须等待前面的运算完成後才能进行下一个运算,也会使运算後变成深层结构 Identity(Identity(3))
,取值时必须
result.val.val
那该怎麽办呢? 有没有方法让其既可以是独立的也可以维持单层结构,就让来介绍 Apply 吧!
Type Signature
ap :: Apply f => f a ~> f (a -> b) -> f b
Law
v.ap(u.ap(a.map(f => g => x => f(g(x))))) === v.ap(u).ap(a)
Implementation
所以要解决上述提到的问题可以分成四步骤
1. 将 add
函式进行 currying
const add = R.curry((x, y) => x + y);
2. 实作 ap
const Identity = (val) => ({
val,
map: (f) => {
const result = f(val);
return Identity(result);
},
ap: function (o) {
// 根据 Fantasy-land 对 Apply 定义,其为 `a.ap(b)` 其 `b` 一定会是函式,而在此范例则是 o.val 必为函式
return this.map(o.val);
},
inspect: () => `Identity(${val})`,
});
3. 建立一个 helper function lift2
const lift2 = g => f1 => f2 => f2.ap(f1.map(g));
注意: 这就为什麽我们的
g
一定要进行 currying
而其实 ap
就是将两个 Container 进行合并,相较於前面章节提过的 Semigroup 则是透过呼叫 concat
将值进行合并。
另外如果今天是要将 g
(3-ary) 合并三个 Container
const lift3 = g => f1 => f2 => f3 => f3.ap(f2.ap(f1.map(g)));
4. 接下来就可以轻松的解决一开始的问题
lift2(add)(Identity(1))(Identity(2)) // Identity(3)
没错,我们现在解决了 effects 跟 pure(n-ary) 的问题!!! 所以来更新一下一开始提到的表吧!
f | g | composition |
---|---|---|
pure | pure | compose(f, g) |
effects | pure(unary) | f.map(g) |
effects | pure(n-ary) | f1.map(g).ap(f2) |
感谢大家的阅读!!
<<: Day 0x15 - 代码建立 (Part 1: 回覆讯息代码)
>>: 30天零负担轻松学会制作APP介面及设计【DAY 22】
取得Nonce 根据规格书的说明,每次呼叫api前都要先取得Nonce 要取得Nonce也满简单的,...
前言 Reactor 是concurrency-agnostic ,花了一点时间研究这个英文单字的意...
今天要来介绍Composite Pattern,是属於Structural Design Pat...
今天想分享一下如何上传自己的 GitHub Pages, 可以参考高见龙的 使用 GitHub 免费...
AutoML得到的结果,说明如下。见图<AZ-exp4MNIST.png> 当看到 [S...