问题
Starting with a simple function composition
const fa = (x => (x + "a"));
const fb = (x => (x + "b"));
fb(fa('x'))
I played around and I obtained the following code snippet which returns 'xba' instead of 'xab'.
Can someone explain why?
const fa = next => x => next(x + "a");
const fb = next => x => next(x + "b");
console.log(fb(fa(y => y))('x'));
回答1:
Let's break this down:
const _fa = fa(y => y)
// _fa = x => (y => y)(x + "a")
To avoid confusing the two x
let's name it as x1
// _fa = x1 => (y => y)(x1 + "a")
Now fb
would be:
// fb = next => x2 => next(x2 + "b")
If we call fb
with fa(y => y)
(ie. _fa
), we substitute next
with _fa
:
_fb = fb(fa(y => y))
// _fb = x2 => (x1 => (y => y)(x1 + "a"))(x2 + "b")
Now lets evaluate _fb
with the argument x2 = 'x'
:
// _fb = (x1 => (y => y)(x1 + "a"))("x" + "b")
// _fb = (x1 => (y => y)(x1 + "a"))("xb")
Notice how x1 => (y => y)(x1 + "a")
can be simplified to x1 => x1 + "a"
. Now we have:
// _fb = (x1 => x1 + "a")("xb")
Now let's evaluate this function (x1 => x1 + "a")
with argument x1 = "xb"
// _fb = "xb" + "a"
// _fb = "xba"
回答2:
You might not know it, but you're looking at the continuation monad! Also the 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
In a slightly more involved example, we illustrate liftA2
which takes a binary function and "lifts" it into our Cont
context. Now we can take two Cont
values and use them with any ordinary function.
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
来源:https://stackoverflow.com/questions/50911297/js-functions-composed-in-the-opposite-order