总结

处理多个 functor 作为参数的情况,是 applicative functor 一个非常好的应用场景。借助 applicative functor,我们能够在 functor 的世界里调用函数。尽管已经可以通过 monad 达到这个目的,但在不需要 monad 的特定功能的时候,我们还是更倾向于使用 applicative functor。

至此我们已经基本介绍完容器的 api 了,我们学会了如何对函数调用 mapchainap。下一章,我们将学习如何更好地处理多个 functor,以及如何以一种原则性的方式拆解它们。

Chapter 11: Traversable/Foldable Functors

练习

  1. require('./support');
  2. var Task = require('data.task');
  3. var _ = require('ramda');
  4. // 模拟浏览器的 localStorage 对象
  5. var localStorage = {};
  6. // 练习 1
  7. // ==========
  8. // 写一个函数,使用 Maybe 和 ap() 实现让两个可能是 null 的数值相加。
  9. // ex1 :: Number -> Number -> Maybe Number
  10. var ex1 = function(x, y) {
  11. };
  12. // 练习 2
  13. // ==========
  14. // 写一个函数,接收两个 Maybe 为参数,让它们相加。使用 liftA2 代替 ap()。
  15. // ex2 :: Maybe Number -> Maybe Number -> Maybe Number
  16. var ex2 = undefined;
  17. // 练习 3
  18. // ==========
  19. // 运行 getPost(n) 和 getComments(n),两者都运行完毕后执行渲染页面的操作。(参数 n 可以是任意值)。
  20. var makeComments = _.reduce(function(acc, c){ return acc+"<li>"+c+"</li>" }, "");
  21. var render = _.curry(function(p, cs) { return "<div>"+p.title+"</div>"+makeComments(cs); });
  22. // ex3 :: Task Error HTML
  23. var ex3 = undefined;
  24. // 练习 4
  25. // ==========
  26. // 写一个 IO,从缓存中读取 player1 和 player2,然后开始游戏。
  27. localStorage.player1 = "toby";
  28. localStorage.player2 = "sally";
  29. var getCache = function(x) {
  30. return new IO(function() { return localStorage[x]; });
  31. }
  32. var game = _.curry(function(p1, p2) { return p1 + ' vs ' + p2; });
  33. // ex4 :: IO String
  34. var ex4 = undefined;
  35. // 帮助函数
  36. // =====================
  37. function getPost(i) {
  38. return new Task(function (rej, res) {
  39. setTimeout(function () { res({ id: i, title: 'Love them futures' }); }, 300);
  40. });
  41. }
  42. function getComments(i) {
  43. return new Task(function (rej, res) {
  44. setTimeout(function () {
  45. res(["This book should be illegal", "Monads are like space burritos"]);
  46. }, 300);
  47. });
  48. }