当我使用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中的需要,或者它是否存在以防万一它是有状态的内部?
答案 0 :(得分:0)
有效函数是来自维基百科的函数pure:
在计算机编程中,如果关于函数的这两个语句都成立,则函数可以被描述为纯函数:
在给定相同参数值的情况下,函数始终评估相同的结果值。函数结果值不能依赖于程序执行过程中或程序的不同执行之间可能发生变化的任何隐藏信息或状态,也不依赖于I / O设备的任何外部输入[...]。
- 醇>
评估结果不会导致任何语义上可观察到的副作用或输出,例如可变对象的突变或输出到I / O设备[...]。
由于DOM存储状态,包含对DOM的调用的函数几乎总是有效的。
有关PureScript的更多详细信息,请参阅Handling Native Effects with the Eff Monad。
答案 1 :(得分:0)
如果函数没有改变状态,并且总是(过去,现在和将来)在给出相同的参数时返回相同的值,那么它不需要返回{{1} ,否则确实如此。
n.tagName
是只读的,据我所知,它永远不会改变。因此,Eff
是纯粹的,可以不返回getTagName
。
另一方面,Eff
函数必须返回getTextContent
。它不会改变状态,但它会在不同的时间返回不同的值。
广泛的浩大的 大多数JS API(包括DOM)都是有效的。 Eff
是非常少数例外之一。因此,在编写FFI时,PureScript作者只是假设所有JS函数都返回getTagName
,即使在他们不需要的极少数情况下也是如此。
值得庆幸的是,purescript-dom
的最新版本对nodeName
,tagName
,localName
等使用了非Eff
函数。