javascript - 通过将参数包装在函数中来延迟评估?

标签 javascript functional-programming monads

《函数式编程基本足够指南》Chapter 8 ,他们定义了一个新类 IO,其定义如下:

class 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 delays the impure action by capturing it in a function wrapper. As such, we think of IO as containing the return value of the wrapped action and not the wrapper itself. This is apparent in the of function: we have an IO(x), the IO(() => x) is just necessary to avoid evaluation.

但是我对 .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() 方法以及如何“避免评估”。此外,作者在 IO 的任何示例中都没有使用 .of(),而是直接调用构造函数。

最佳答案

为了使 IO 成为单子(monad)(根据该书的单子(monad)概念),它需要一个 .of 方法,该方法可以将任何任意值包装在 IO。 IO.of 就是这样做的。由于本书IO实现的本质是它们带有一个可以在稍后计算的函数,因此.of方法将传递的值包装在函数中.

IO.of(5) 创建包装值 5IO 实例。就这些。 .of 中没有任何内容会真正延迟效果。

关于评论中的问题:

Then what does the author mean by saying "This is apparent in the of function: we have an IO(x), the IO(() => x) is just necessary to avoid evaluation."

我认为理解该评论所需的信息就是它前面的内容:

We don't think of its $value as a function, however - that is an implementation detail and we best ignore it. ... As such, we think of IO as containing the return value of the wrapped action and not the wrapper itself.

他的观点似乎是,从概念上讲,IO 的“值”是所包含函数最终求值的值,但为了实现延迟求值,它在内部存储了一个未求值的值。函数直到 IO 需要解析为一个值为止。

因此,您可以通过调用 IO.of(5) 为值 5 创建一个 IO,但在内部,它包含一个函数其计算结果为 5,以便稍后可以将该函数计算为一个值。

如果您想创建一个实际上延迟某些不纯效果的评估的 IO,请使用构造函数并向其传递一个函数。

关于javascript - 通过将参数包装在函数中来延迟评估?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59541760/

相关文章:

javascript - 具有 apache 别名的已用服务人员无法正常工作

haskell - Monad 从 Lift 移植到 Yesod 的 Persistent 时遇到麻烦

javascript - 如何使用jquery缩放相同质量的图像?

javascript - 如何使用nodejs检查DNS?

javascript - Angular 中的全局保存按钮

haskell - 创建 "type"的任意实例

javascript - 获得另一个属性指向的属性的最干净的 fp 方法是什么

unit-testing - OCaml 使用异步编写超时函数

haskell - 为所有仿函数推广 "sequence"?

javascript - 使用 MVars 在 Haskell 中实现事件流