在《函数编程基本指南》中第八章,他们定义了一个新的类,IO,定义如下:
lass IO {
static of(x) {
return new IO(() => x);
}
constructor(fn) {
this.$value = fn;
}
map(fn) {
return new IO(compose(fn, this.$value));
}
inspect() {
return `IO(${inspect(this.$value)})`;
}
}
作者解释说:IO通过在函数包装器中捕获不纯的动作来延迟它。因此,我们认为IO包含包装动作的返回值,而不是包装本身。这在of函数中是显而易见的:我们有一个IO(x),IO(() => x)只是为了避免评估。 但是我很困惑.of()方法会延迟评估。例如,从该部分的开头偏离定义,
// getFromStorage :: String -> (_ -> String)
const getFromStorage = key => () => localStorage[key];
如果我尝试创造一个新的IO像IO.of(localStorage[42]),例如,这不会延迟评估的价值(localStorage[42]),会立即评估(假设评估结果为“foo”),然后是新的IO对象将使用{ $value: () => "foo" }
我理解如何调用构造函数立即喜欢新输入输出new IO(key => () => localStorage[key])延迟评估,但我不明白作者使用.of()方法以及如何“避免评估”。此外,作者不使.of()在的任何示例中IO,而是直接调用构造函数。
为了IO要成为单子(根据那本书对单子的概念),它需要一个.of方法,该方法可以将任意值包装在IO.的IO那样做。由于这本书的实施性质IO它们带有一个可以在以后某个时候评估的函数.of方法将传递的值包装在函数中。
(5)的IO创建的实例信息作战包装这个值5.仅此而已。没有关于。关于这实际上延迟了效果。
关于您在评论中的问题: 那么作者所说的“这在关于功能:我们有一个IO(x), IO(() => x)只是为了避免评估。"
我认为理解这一评论所必需的信息是摆在它面前的:
然而,我们并不认为它的价值是一个函数——这是一个实现细节,我们最好忽略它。...因此,我们认为IO包含包装动作的返回值,而不是包装本身。
他的观点似乎是,从概念上来说IO's“value”是包含的函数最终评估的值,但是为了实现延迟评估,它在内部存储未评估的函数,直到信息作战解析为一个值。
所以你可以创建一个信息作战为了价值5通过IO.of(5) ,但在内部,它包含一个计算结果为的函数5,以便在以后某个时候可以将该函数计算为一个值。
如果您想创建一个IO这实际上延迟了一些不纯效果的评估,使用构造函数并传递给它一个函数。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。