0

当我使用 FFI 包装一些 API(例如 DOM API)时,是否有任何经验法则可以帮助我决定函数是否应该有效?

这是一个例子:

foreign import querySelectorImpl """
    function querySelectorImpl (Nothing) {
      return function (Just) {
        return function (selector) {
          return function (src) {
            return function () {
              var result = src.querySelector(selector);
              return result ? Just(result) : Nothing;
            };
          };
        };
      };
    }
  """ :: forall a e. Maybe a -> (a -> Maybe a) -> String -> Node -> Eff (dom :: DOM | e) (Maybe Node)

querySelector :: forall e. String -> Node -> Eff (dom :: DOM | e) (Maybe Node)
querySelector = querySelectorImpl Nothing Just

foreign import getTagName """
    function getTagName (n) {
      return function () {
        return n.tagName;
      };
    }
  """ :: forall e. Node -> Eff (dom :: DOM | e) String

感觉querySelector很有效,但我不太确定getTagName

更新:

我明白什么是纯函数,它不应该改变程序的状态,也许 DOM 是一个不好的例子。

我问这个问题是因为在大多数包装现有 js 库的库中,几乎每个函数都是有效的,即使感觉不对。所以也许我的实际问题是 - 这种效果是否代表了这个包装好的 js lib 中的需要,或者它是否存在以防万一它内部是有状态的?

4

2 回答 2

0

有效函数是非 pure 的函数来自维基百科:

在计算机编程中,如果关于函数的以下两个陈述都成立,则函数可以被描述为纯函数:

  1. 给定相同的参数值,该函数始终评估相同的结果值。函数结果值不能依赖于任何隐藏信息或状态,这些信息或状态可能会随着程序执行的进行或在程序的不同执行之间发生变化,也不能依赖于来自 I/O 设备的任何外部输入 [...]。

  2. 结果的评估不会导致任何语义上可观察的副作用或输出,例如可变对象的突变或输出到 I/O 设备 [...]。

由于 DOM 存储状态,因此包装对 DOM 的调用的函数几乎总是有效的。

有关 PureScript 的更多详细信息,请参阅使用 Eff Monad 处理原生效果

于 2015-06-22T15:20:39.673 回答
0

如果一个函数没有改变状态,并且在给定相同的参数时它总是(过去、现在和将来)返回相同的值,那么它不需要 return Eff,否则它会。

n.tagName是只读的,据我所知,它永远不会改变。因此,getTagName是纯粹的,不返回也没关系Eff

另一方面,getTextContent函数必须返回Eff。它不会改变状态,但会在不同的时间返回不同的值。

绝大多数JS API(包括 DOM)都是有效的少数例外之一。因此,在编写 FFI 时,PureScript 作者只是假设所有 JS 函数 return ,即使在他们不需要的极少数情况下也是如此。getTagNameEff

值得庆幸的是,最新版本的purescript-domEff函数用于nodeName, tagName,localName等。

于 2016-11-02T08:02:27.067 回答