总结
我们已经认识了几个不同的 functor,但它们的数量其实是无限的。有一些值得注意的可迭代数据类型(iterable data structure)我们没有介绍,像 tree、list、map 和 pair 等,以及所有你能说出来的。eventstream 和 observable 也都是 functor。其他的 functor 可能就是拿来做封装或者仅仅是模拟类型。我们身边到处都有 functor 的身影,本书也将会大量使用它们。
用多个 functor 参数调用一个函数怎么样呢?处理一个由不纯的或者异步的操作组成的有序序列怎么样呢?要应对这个什么都装在盒子里的世界,目前我们工具箱里的工具还不全。下一章,我们将直奔 monad 而去。
练习
require('../../support');
var Task = require('data.task');
var _ = require('ramda');
// 练习 1
// ==========
// 使用 _.add(x,y) 和 _.map(f,x) 创建一个能让 functor 里的值增加的函数
var ex1 = undefined
//练习 2
// ==========
// 使用 _.head 获取列表的第一个元素
var xs = Identity.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do']);
var ex2 = undefined
// 练习 3
// ==========
// 使用 safeProp 和 _.head 找到 user 的名字的首字母
var safeProp = _.curry(function (x, o) { return Maybe.of(o[x]); });
var user = { id: 2, name: "Albert" };
var ex3 = undefined
// 练习 4
// ==========
// 使用 Maybe 重写 ex4,不要有 if 语句
var ex4 = function (n) {
if (n) { return parseInt(n); }
};
var ex4 = undefined
// 练习 5
// ==========
// 写一个函数,先 getPost 获取一篇文章,然后 toUpperCase 让这片文章标题变为大写
// getPost :: Int -> Future({id: Int, title: String})
var getPost = function (i) {
return new Task(function(rej, res) {
setTimeout(function(){
res({id: i, title: 'Love them futures'})
}, 300)
});
}
var ex5 = undefined
// 练习 6
// ==========
// 写一个函数,使用 checkActive() 和 showWelcome() 分别允许访问或返回错误
var showWelcome = _.compose(_.add( "Welcome "), _.prop('name'))
var checkActive = function(user) {
return user.active ? Right.of(user) : Left.of('Your account is not active')
}
var ex6 = undefined
// 练习 7
// ==========
// 写一个验证函数,检查参数是否 length > 3。如果是就返回 Right(x),否则就返回
// Left("You need > 3")
var ex7 = function(x) {
return undefined // <--- write me. (don't be pointfree)
}
// 练习 8
// ==========
// 使用练习 7 的 ex7 和 Either 构造一个 functor,如果一个 user 合法就保存它,否则
// 返回错误消息。别忘了 either 的两个参数必须返回同一类型的数据。
var save = function(x){
return new IO(function(){
console.log("SAVED USER!");
return x + '-saved';
});
}
var ex8 = undefined