难以理解函数式编程的组成,函子和monad示例

时间:2019-07-28 19:40:49

标签: javascript functional-programming

我已经掌握了一些有关函数式编程的知识,但实际上并不能完全围绕这个函数式编程代码进行研究。我真的不知道该在哪里问这样的问题,所以我在这里问了。因此,如果有人能帮助我了解这个高阶函数或一个monads的例子,我将不胜感激。

P.S该代码来自Eric Elliot撰写的软件书

const f = n => n+1;
const g = n => n*2;

composeM函数是为了组成和映射或映射多个函数?我知道reduce,但真的不知道该功能应该如何工作。

const composeM = (...mps) => mps.reduce((f, g) => x => g(x).map(f));
const h = composeM(f,g);
h(20)

然后,通过执行以下操作使函数composeM更加通用化:

const compose = methods => (...mps) => mps.reduce((f, g) => x => g(x)[method](f));

然后,我可以像创建composedPromisescomposedMaps

const composePromises = compose("then")(f,g);

g(x)[method](f)怎么工作?应该是g(x).then(f)

更新以上地图的composeM功能

const f = n => Promise.resolve( n+1 );
const g = n => Promise.resolve( n*2 );

const composePromises = (...mps) => mps.reduce((f, g) => x => g(x).then(f))
const h = composePromises(f, g)
h(20)

1 个答案:

答案 0 :(得分:1)

考虑具有以下类型签名的函数组成。

// compose :: (b -> c) -- The 1st argument is a function from b to c.
//         -> (a -> b) -- The 2nd argument is a function from a to b.
//         -> (a -> c) -- The final result is a function from a to c.

//               +-----------------b -> c
//               |  +---------a -> b
//               |  |     +-- a
//               |  |     |
const compose = (f, g) => x => f(g(x));
//                             |_____|
//                                |
//                                c

composeP函数与compose函数相似,不同之处在于它包含返回诺言的函数。

// composeP :: (b -> Promise c) -- The 1st argument is a function from b to promise of c.
//          -> (a -> Promise b) -- The 2nd argument is a function from a to promise of b.
//          -> (a -> Promise c) -- The final result is a function from a to promise of c.

//                +-------------------------b -> Promise c
//                |  +-------- a -> Promise b
//                |  |     +-- a
//                |  |     |
const composeP = (f, g) => x => g(x).then(f);
//                              |__________|
//                                   |
//                               Promise c

请记住,then方法将回调函数应用于promise的值。如果我们将.then替换为[method],其中method是特定monad的bind函数的名称,那么我们可以组成产生该monad值的函数。

例如,.flatMap是数组的绑定函数。因此,我们可以编写返回数组的函数,如下所示。

// composeA :: (b -> Array c) -- The 1st argument is a function from b to array of c.
//          -> (a -> Array b) -- The 2nd argument is a function from a to array of b.
//          -> (a -> Array c) -- The final result is a function from a to array of c.

const composeA = (f, g) => x => g(x).flatMap(f);

// f :: Bool -> Array String
const f = x => x ? ["yes"] : ["no"];

// g :: Int -> Array String
const g = n => [n <= 0, n >= 0];

// h :: Int -> Array String
const h = composeA(f, g);

console.log(h(-1)); // ["yes", "no"]
console.log(h(0));  // ["yes", "yes"]
console.log(h(1));  // ["no",  "yes"]

那是一个非常人为的例子,但它说明了要点。

无论如何,通用compose函数由monad组成。

const compose = method => (f, g) => x => g(x)[method](f);

const composeP = compose("then");
const composeA = compose("flatMap");

最后,各种monad compose函数一次只能组成两个函数。我们可以使用reduce一次组成其中的几个。希望有帮助。