以相反顺序组合的 JS 函数
JS functions composed in the opposite order
从一个简单的函数组合开始
const fa = (x => (x + "a"));
const fb = (x => (x + "b"));
fb(fa('x'))
我试了一下,获得了以下代码片段,其中 returns 'xba' 而不是 'xab'。
有人可以解释为什么吗?
const fa = next => x => next(x + "a");
const fb = next => x => next(x + "b");
console.log(fb(fa(y => y))('x'));
让我们分解一下:
const _fa = fa(y => y)
// _fa = x => (y => y)(x + "a")
为了避免混淆这两个 x
我们将其命名为 x1
// _fa = x1 => (y => y)(x1 + "a")
现在 fb
将是:
// fb = next => x2 => next(x2 + "b")
如果我们用fa(y => y)
调用fb
(即_fa
),我们用_fa
代替next
:
_fb = fb(fa(y => y))
// _fb = x2 => (x1 => (y => y)(x1 + "a"))(x2 + "b")
现在让我们用参数 x2 = 'x'
:
计算 _fb
// _fb = (x1 => (y => y)(x1 + "a"))("x" + "b")
// _fb = (x1 => (y => y)(x1 + "a"))("xb")
注意如何将 x1 => (y => y)(x1 + "a")
简化为 x1 => x1 + "a"
。现在我们有:
// _fb = (x1 => x1 + "a")("xb")
现在让我们用参数 x1 = "xb"
计算这个函数 (x1 => x1 + "a")
// _fb = "xb" + "a"
// _fb = "xba"
你可能不知道,但你正在看延续 monad!还有 thrush combinator.
const Cont = someValue => next =>
next (someValue)
const fa = x =>
Cont (x + "a")
const fb = x =>
Cont (x + "b")
fa ("x") (fb) (console.log)
// xab
fb ("x") (fa) (console.log)
// xba
fa ("x") (fa) (fa) (fa) (fb) (console.log)
// xaaaab
fb ("x") (fa) (fb) (fa) (fb) (console.log)
// xbabab
在一个稍微复杂一点的例子中,我们说明了 liftA2
它接受一个二元函数并且 "lifts" 它进入我们的 Cont
上下文。现在我们可以取两个 Cont
值并将它们用于任何普通函数。
const Cont = someValue => next =>
next (someValue)
const liftA2 = f => mx => my =>
mx (x =>
my (y =>
Cont (f (x, y))))
const mult = (x, y) =>
x * y
const main =
liftA2 (mult) (Cont (6)) (Cont (7))
main (console.log)
// 42
main (x => Cont (x + 1)) (console.log)
// 43
从一个简单的函数组合开始
const fa = (x => (x + "a"));
const fb = (x => (x + "b"));
fb(fa('x'))
我试了一下,获得了以下代码片段,其中 returns 'xba' 而不是 'xab'。
有人可以解释为什么吗?
const fa = next => x => next(x + "a");
const fb = next => x => next(x + "b");
console.log(fb(fa(y => y))('x'));
让我们分解一下:
const _fa = fa(y => y)
// _fa = x => (y => y)(x + "a")
为了避免混淆这两个 x
我们将其命名为 x1
// _fa = x1 => (y => y)(x1 + "a")
现在 fb
将是:
// fb = next => x2 => next(x2 + "b")
如果我们用fa(y => y)
调用fb
(即_fa
),我们用_fa
代替next
:
_fb = fb(fa(y => y))
// _fb = x2 => (x1 => (y => y)(x1 + "a"))(x2 + "b")
现在让我们用参数 x2 = 'x'
:
_fb
// _fb = (x1 => (y => y)(x1 + "a"))("x" + "b")
// _fb = (x1 => (y => y)(x1 + "a"))("xb")
注意如何将 x1 => (y => y)(x1 + "a")
简化为 x1 => x1 + "a"
。现在我们有:
// _fb = (x1 => x1 + "a")("xb")
现在让我们用参数 x1 = "xb"
(x1 => x1 + "a")
// _fb = "xb" + "a"
// _fb = "xba"
你可能不知道,但你正在看延续 monad!还有 thrush combinator.
const Cont = someValue => next =>
next (someValue)
const fa = x =>
Cont (x + "a")
const fb = x =>
Cont (x + "b")
fa ("x") (fb) (console.log)
// xab
fb ("x") (fa) (console.log)
// xba
fa ("x") (fa) (fa) (fa) (fb) (console.log)
// xaaaab
fb ("x") (fa) (fb) (fa) (fb) (console.log)
// xbabab
在一个稍微复杂一点的例子中,我们说明了 liftA2
它接受一个二元函数并且 "lifts" 它进入我们的 Cont
上下文。现在我们可以取两个 Cont
值并将它们用于任何普通函数。
const Cont = someValue => next =>
next (someValue)
const liftA2 = f => mx => my =>
mx (x =>
my (y =>
Cont (f (x, y))))
const mult = (x, y) =>
x * y
const main =
liftA2 (mult) (Cont (6)) (Cont (7))
main (console.log)
// 42
main (x => Cont (x + 1)) (console.log)
// 43